难道我纠正异步/ AWAIT本身无关并发/并行性,无非是延续传递风格(CPS)实现的更多? 而真正的线程被执行SynchronizationContext
该实例await
通行证/恢复?
如果这是正确的我对以下问题SynchronizationContext
:
它保证的延续将在同一线程上执行。
然而,是否有该线程的上下文信息被永久保存的任何担保? 我的意思是Name
, CurrentPrincipal
, CurrentCulture
, CurrentUICulture
等是否依赖于框架(ASP.NET,WinForms的,WCF,WPF)?
我是正确的是异步/ AWAIT本身无关并发/并行性,无非是CPS实现的更多?
那么, async
/ await
是使用CPS重写,所以你的核心的理解是正确的。
关于“并发”和“并行”,我会说,它确实使并发; 你可以启动多个async
同时操作,这些操作都是“飞行”。 这是容易做到Task.WhenAll
和Task.WhenAny
。
此外,即使async
本身并不意味着“多线程”, Task.Run
确实能够轻松async
兼容多线程
而真正的线程是由等待通行证/恢复的SynchronizationContext实例执行?
想想这样的方式:由CPS重写创建的延续有什么地方运行。 所捕获的“异步上下文”可被用于调度的延续。
附注:捕捉的情况下实际上是SynchronizationContext.Current
除非它为空 ,在这种情况下拍摄的背景是TaskScheduler.Current
。
另一个重要的注意事项:捕捉和上下文的恢复实际上是上升到“awaiter”对象。 因此,在默认情况下,如果你await
一个Task
(或任何其他内置awaitable),上下文将被捕获和恢复。 但是,如果你await
的结果ConfigureAwait(false)
,那么上下文没有捕获。 同样,如果您await
自己的自定义awaitable,也不会捕捉范围内(除非你对编程)。
然而,是否有该线程的上下文信息被永久保存的任何担保? 我的意思是名称,CurrentPrincipal,的CurrentCulture,的CurrentUICulture,等等。
SynchronizationContext
比不同ExecutionContext
。 简化的答案是ExecutionContext
始终是“流动”,所以CurrentPrincipal
流(如果它没有,它可能是一个安全问题,这就是为什么不流动的API ExecutionContext
始终在结束Unsafe
)。
在UI应用,文化不流动,但默认情况下它的所有线程在同一反正。 Name
是绝对不会流出,除非你继续在同一个线程(例如,使用UI SynchronizationContext
)。
对于一些进一步的阅读,我建议首先是我自己的async
/ await
教程 ,然后正式async
/ await
FAQ 。 然后看看斯蒂芬Toub的博客文章ExecutionContext
对比SynchronizationContext
。
您也可以找到我SynchronizationContext
文章很有帮助。
不, async
/ await
关键字具有一切与并发性。 async
/ await
基本包装你的方法代码的任务和延续。 要看到,编译器生成(使用任务并行库)的精确翻译,拆解一些代码段。 这个翻译async
/ await
用法是“相似”(但不完全相同!)下面的例子
async Task<int> TaskOfTResult_MethodAsync()
{
int hours;
// . . .
// Return statement specifies an integer result.
return hours;
}
// Calls to TaskOfTResult_MethodAsync
Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();
int intResult = await returnedTaskTResult;
// or, in a single statement
int intResult = await TaskOfTResult_MethodAsync();
这approxiamtely转换为
private int Result()
{
int hours;
// . . .
// Return statement specifies an integer result.
return hours;
}
在您等待的方法外返回喜欢
int? hours = null;
Task<int> task = null;
task = Task.Factory.StartNew<int>(() => Result());
task.ContnueWith(cont =>
{
// Some task completion checking...
hours = task.Result;
}, CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Current);
或者,你可以放置TPL代码到Result
的方法
private int ResultAsync()
{
int? hours = null;
Task<int> task = null;
task = Task.Factory.StartNew<int>(() =>
{
int hours;
// . . .
// Return statement specifies an integer result.
return hours;
}, CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Current);
try
{
return task.Result;
}
catch (AggregateException aggEx)
{
// Some handler method for the agg exception.
aggEx.Handle(HandleException);
}
}
SynchronizationContext
不保证会继续为相同的线程上执行async
/ awate
代码。 但是,您可以设置使用TPL代码的情况下,通过SynchronisationContex
关键字。