c# - 异步转同步 - configureawait用法




C#5异步/等待-是*并发*? (3)

我一直在考虑C#5中新的异步内容,并提出了一个特别的问题。

我知道await关键字是一个简洁的编译器技巧/语法糖来实现继续传递 ,其中方法的其余部分被分解为Task对象并排队等待按顺序运行,但是控制返回给调用方法。

我的问题是,我听说目前这一切都在一个线程上。 这是否意味着这种异步内容实际上只是将连续代码转换为Task对象,然后在每个任务完成之后调用Application.DoEvents()然后启动下一个Task对象?

或者我错过了什么? (问题的这一部分是修辞 - 我完全清楚我错过了什么 :))


async / await的真正“meat”(异步)部分通常是单独完成的,与调用者的通信是通过TaskCompletionSource完成的。 正如这里所写http://blogs.msdn.com/b/pfxteam/archive/2009/06/02/9685804.aspx

TaskCompletionSource类型有两个相关的目的,它们的名称都提到:它是创建任务的源,也是该任务完成的源。 实质上,TaskCompletionSource充当Task及其完成的生产者。

这个例子很清楚:

public static Task<T> RunAsync<T>(Func<T> function) 
{ 
    if (function == null) throw new ArgumentNullException(“function”); 
    var tcs = new TaskCompletionSource<T>(); 
    ThreadPool.QueueUserWorkItem(_ => 
    { 
        try 
        {  
            T result = function(); 
            tcs.SetResult(result);  
        } 
        catch(Exception exc) { tcs.SetException(exc); } 
    }); 
    return tcs.Task; 
}

通过TaskCompletionSource您可以访问可以等待的Task对象,但不是通过您创建多线程的async / await关键字。

请注意,当许多“慢”函数转换为async / await语法时,您不需要非常使用TaskCompletionSource 。 他们将在内部使用它(但最终某处必须有一个TaskCompletionSource才能产生异步结果)


async / await背后的整个想法是它很好地执行continuation传递,并且不为该操作分配新线程。 继续可能发生在新线程上,它可能在同一线程上继续。


我想解释它的方式是“await”关键字只是等待一个任务完成,但在等待时产生执行到调用线程。 然后它返回Task的结果,并在Task完成后从“await”关键字后面的语句继续。

我注意到的一些人似乎认为Task与调用线程在同一个线程中运行,这是不正确的,可以通过尝试在等待调用的方法中更改Windows.Forms GUI元素来证明。 但是,继续在尽可能在调用线程中运行。

它只是一个简洁的方式,无需在任务完成时拥有回调委托或事件处理程序。





async-await