加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#任务ConfigureAwait

发布时间:2020-12-15 18:16:02 所属栏目:百科 来源:网络整理
导读:以为我正在处理ConfigureAwait,然后我尝试了一个实验. 我的理解是,只有存在同步上下文时,ConfigureAwait(false)才会有所不同. ASP,WPF等应该有一个上下文,但控制台应用程序和服务应用程序不应该. 为了了解它是如何工作的,我制作了一个Web API应用程序并包含
以为我正在处理ConfigureAwait,然后我尝试了一个实验.

我的理解是,只有存在同步上下文时,ConfigureAwait(false)才会有所不同.

ASP,WPF等应该有一个上下文,但控制台应用程序和服务应用程序不应该.

为了了解它是如何工作的,我制作了一个Web API应用程序并包含以下方法:

// GET api/values/5
public async Task<string> Get (int id)
{
    var syncCtx = SynchronizationContext.Current;

    int startThreadId = Thread.CurrentThread.ManagedThreadId;

    await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(true);

    int endThreadId = Thread.CurrentThread.ManagedThreadId;

    return "Start Thread ID: " + startThreadId.ToString() + 
            ": End Thread ID: " + endThreadId.ToString();
}

我的预测是,如果没有将ConfigureAwait或ConfigureAwait设置为true,我应该在await之前和之后看到相同的线程ID.

我的前几个测试确切地显示了上面的真实设置.

无论ConfigureAwait如何,代码的后续运行都会在不同的线程ID上启动和结束.

我添加了syncCtx来说服自己我有一个上下文.

我读过的一个警告是,如果任务完成,您将无法保证具有相同的ID.这是这种情况吗?如果是这样,为什么会这样呢?

我是否设置了天真或有缺陷的测试?如果是这样,那么适当的测试是什么?

我在控制台/服务应用程序中开始这条路径,并意识到我没有获得相同的线程ID.我在大多数“最佳实践”写作中建议我添加ConfigureAwait(false).因为我喜欢看事情是如何工作的,所以我尝试测试线程ID.看到它们的不同使我经历了一些导致上述代码的搜索.

解决方法

执行ConfigureAwait(true)(或者只是将其关闭,因为它是默认值)不会使它在同一个线程上运行.它告诉SynchronizationContext.Current在继续的其余部分执行 PostSend. Post或Send实际上如何运行该代码未定义.

WindowsFormsSynchronizationContext和DispatcherSynchronizationContext(WinForms和WPF的上下文)都将延续到消息泵(UI线程)要处理的消息队列.

另一方面,AspNetSynchronizationContext(你正在运行它)只是设置一些状态信息(比如将HttpContext.Current设置回旧值),然后它将工作排在下一个可用的线程池线程上. ASP.NET中没有“消息泵”,它只是在线程池上完成所有工作,因此以后尝试从线程池中获取相同的线程是没有意义的,该线程可能已经在继续发生的时候被摧毁了.

您在幸运之前和之后看到相同ID的时间,并且在继续之前和之后相同的线程被拉出线程池.

我强烈建议您阅读MSDN杂志文章“It’s All About the SynchronizationContext”,它详细解释了SynchronizationContext的工作原理,并详细介绍了.NET内置的4种类型的上下文.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读