首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当异步方法完成时等待部分代码被调用/执行

当异步方法完成时等待部分代码被调用/执行
EN

Stack Overflow用户
提问于 2020-12-17 12:41:48
回答 2查看 53关注 0票数 1

我读过关于C#中的异步编程的文章,但我仍然不完全理解异步方法的延续是如何执行的。据我理解,异步编程与多线程无关。我们可以在UI上运行异步方法,稍后它将继续在该UI线程上运行(同时不阻塞并继续响应消息循环中的其他消息)。

这是大多数GUI应用程序的基本消息循环:

代码语言:javascript
运行
复制
while (1)
{
    bRet = GetMessage(&msg, NULL, 0, 0);

    if (bRet > 0)  // (bRet > 0 indicates a message that must be processed.)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    ...

DispatchMessage()调用UI事件处理程序。事件处理程序中的代码不应该阻塞主线程。因此,如果我们想要创建一个从磁盘加载大量数据的按钮,我们可以使用如下的异步方法:(简化伪代码)

代码语言:javascript
运行
复制
public async Task ButtonClicked()
{
  loadingBar.Show();
  await AsyncLoadData();
  loadingBar.Hide();
}

当执行到达await AsyncLoadData();行时,它存储上下文并返回任务对象。DispatchMessage()完成,消息循环重复出现在bRet = GetMessage(&msg, NULL, 0, 0);行。

所以我的问题是,rest代码是如何执行的?异步操作是否会触发一条新消息,然后由DispatchMessage()再次处理?或者消息循环有另一个方法(分派后),它检查已完成的异步操作?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-17 13:37:17

所以我的问题是,rest代码是如何执行的?异步操作是否会触发一条新消息,然后由DispatchMessage()再次处理?或者消息循环有另一个方法(分派后),它检查已完成的异步操作?

默认情况下,await将捕获一个“上下文”,并使用该上下文恢复方法的执行。这个“上下文”是SynchronizationContext.Current,回到了TaskScheduler.Current。UI应用程序提供SynchronizationContext,例如WindowsFormsSynchronizationContextDispatcherSynchronizationContext。当await完成时,它会将该方法的延续安排在该上下文上(在本例中,是在SynchronizationContext上)。

对于WinForms,Control.BeginInvoke,它将发布一条Win32消息,也就是由WinProc处理

对于WPF,Dispatcher,其中将回调添加到调度队列。。这个队列也是由Win32 WinProc循环处理的

票数 3
EN

Stack Overflow用户

发布于 2020-12-17 13:07:09

Alex在这方面写了一本很棒的书,它被称为“C# 5中的异步”,我强烈建议阅读它。我不能说这背后的低层次细节,但在高级别CLR会创建如下内容:

代码语言:javascript
运行
复制
void __buttoncliked_remaining_code_1(...) { 
    loadingBar.Hide(); 
} 

因此,将触发一个特定的事件,指示异步作业已经完成。然后,__buttoncliked_remaining_code_1()将像任何常规的C#函数一样,按时间顺序执行。CLR将用于任何线程,但它很可能会重用遇到的一个等待关键字,在您的例子中,这个关键字可能是GUI线程。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65340943

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档