jef*_*a00 6 c# multithreading asynchronous
以为我正在处理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();
}
Run Code Online (Sandbox Code Playgroud)
我的预测是,如果没有ConfigureAwait或ConfigureAwait设置为true,我应该在await之前和之后看到相同的线程ID.
我的前几个测试确切地显示了上面的真实设置.
无论如何,代码的后续运行在不同的线程ID上开始和结束ConfigureAwait.
我补充syncCtx说服自己我有一个背景.
我读过的一个警告是,如果任务完成,您将无法保证具有相同的ID.这是这种情况吗?如果是这样,为什么会这样呢?
我是否设置了天真或有缺陷的测试?如果是这样,那么适当的测试是什么?
我在控制台/服务应用程序中开始这条路径,并意识到我没有获得相同的线程ID.我ConfigureAwait(false)在大多数"最佳实践"写作中添加了我所看到的建议.因为我喜欢看事情是如何工作的,所以我尝试测试线程ID.看到它们的不同使我经历了一些导致上述代码的搜索.
执行ConfigureAwait(true)(或者只是将其关闭,因为它是默认值)不会使它在同一个线程上运行.它告诉SynchronizationContext.Current你做一个Post或Send与其余的继续.Post或Send实际上如何运行该代码未定义.
WindowsFormsSynchronizationContext和DispatcherSynchronizationContext(WinForms和WPF的上下文)都将延续到消息泵(UI线程)要处理的消息队列.
另一方面,AspNetSynchronizationContext(正在运行的是)只是设置一些状态信息(比如设置HttpContext.Current回旧值),然后将工作排队到下一个可用的线程池线程.ASP.NET中没有"消息泵",它只是在线程池上完成所有工作,因此以后尝试从线程池中获取相同的线程是没有意义的,该线程可能已经在继续发生的时候被摧毁了.
您在幸运之前和之后看到相同ID的时间,并且在继续之前和之后相同的线程被拉出线程池.
我强烈建议您阅读MSDN杂志上的文章" 它是关于SynchronizationContext的全部内容 ",它详细解释了SynchronizationContext的工作原理,并详细介绍了.NET内置的4种类型的上下文.
SynchronizationContext!= Thread.如果你正在使用像WPF这样的东西,Dispatcher那么,是的,它 SynchronizationContext恰好与一个特定的线程相关联.然而,像ASP.NET和WCF这样的东西并不是线程仿射,它们只是随身携带特定的环境上下文,需要在接下来开始执行的任何线程上恢复.它们可能与特定线程池相关,但同样不是特定线程.
这正是SynchronizationContext引入抽象的原因:它允许不同的框架确切地确定亲和力对它们意味着什么,并允许异步/等待基础设施以完全不可知的方式在它们之上工作.
| 归档时间: |
|
| 查看次数: |
2250 次 |
| 最近记录: |