发生在C#异步CTP的`awaiting`主题是什么? [英] What happens to an `awaiting` thread in C# Async CTP?
问题描述
我一直在阅读有关新的异步等待
关键字,听起来真棒,但我一直没能找到答案的一个关键问题任何的介绍视频我到目前为止看到(我也看过白皮书而回)。
假设我有打电话给等待
在主UI线程上一个嵌套函数。发生了什么线程在这一点?是否控制返回到消息循环和UI线程可以自由地处理其他投入?
在等待任务完成,并在整个堆叠将被推到一个消息队列中,这样的控制将返回通过每个这样的嵌套函数,或者是别的东西完全发生在这里?
和第二(虽然我有你的注意),我真的不明白,为什么异步方法必须标有异步
。不能任何方法来异步执行?如果我想要异步执行的方法,但它没有一个异步的关键字 - 是有办法做到这一点仅仅
干杯。 :)
编辑: 诚然,如果我能得到的样品code编译我很可能只是明白这一点我自己,但由于种种原因,我跑成块存在。我真正想知道的是它延续下去什么程度?它冻结整个调用堆栈,任务完成时恢复它,还是它只是回去这么远吗?有没有一个函数本身需要以支持延续,或(如我原来问),它继续在整个调用堆栈被标记为异步?
如果它的不的冻结整个调用堆栈,当异步等待打非异步调用函数会发生什么?是否阻止呢?那不是打败计谋的地步?我希望你能看到我缺少一些理解在这里,我希望有人能填补这样我就可以继续学习这一点。
假设我有一个电话在主UI线程上一个嵌套函数等待。发生了什么线程在这一点?是否控制返回到消息循环和UI线程可以自由地处理其他投入?
是的。当你计谋
的awaitable(如任务< TResult>
),在<$ C线的当前位置$ C>异步方法被抓获。然后排队时awaitable完成后要执行的方法(即延续)的剩余部分(例如,当一个任务&LT; TResult&GT;
完成)。
不过,有一个优化的,可以采取的地方:如果awaitable已经完成了,那么等待
不必等待,而它只是继续执行方法立即。这就是所谓的快速路径,<一href="http://blogs.msdn.com/b/lucian/archive/2011/04/15/async-ctp-refresh-design-changes.aspx">described这里。
在等待任务完成,并在整个堆叠将被推到一个消息队列中,这样的控制将返回通过每个这样的嵌套函数,或者是别的东西完全发生在这里?
线程的当前位置被压入的UI消息队列。细节更为复杂一点:延续计划于 TaskScheduler.FromCurrentSynchronizationContext
除非 SynchronizationContext.Current
是空
,在这种情况下,他们被安排在 TaskScheduler.Current
。另外,这一行为可以通过调用重写 ConfigureAwait(假)
,它总是调度延续线程池。由于 SynchronizationContext.Current
是一个UI 的SynchronizationContext
的WPF /的WinForms / Silverlight的,这延续并被推到UI消息队列中。
和第二(虽然我有你的注意),我真的不明白,为什么异步方法需要被贴上异步。不能任何方法来异步执行?如果我想要异步执行的方法,但它没有一个异步的关键字 - 是有办法做到这一点仅仅
?
这些都是字稍有不同的含义异步。该异步
关键字使得计谋
关键字。换句话说,异步
方法可计谋
。老式的异步委托(即的BeginInvoke
/ EndInvoke会
)比异步<很大的不同/ code>。异步委托在
线程池
线程中执行,但异步
方法在UI线程上执行(假设他们是从一个叫用户界面方面,你不叫 ConfigureAwait(假)
)。
如果你想有一个(非 - 异步
)在线程池
线程方式运行,你可以做它是这样的:
等待Task.Run(()=&GT;的MyMethod(..));
我真正想知道的是它延续下去什么程度?它冻结整个调用堆栈,任务完成时恢复它,还是它只是回去这么远吗?有没有一个函数本身需要以支持延续,或(如我原来问),它继续在整个调用堆栈被标记为异步?
当前位置被捕获,并继续延续运行时。使用任何功能等待
来支持延续必须注明异步
。
如果你调用一个异步
从非方法 - 异步
方法,那么你必须处理工作
对象直接。这是不正常完成。顶级异步
方法可以返回无效
,所以没有理由不拥有异步
事件处理程序。
注意异步
纯粹是一个编译器转换。这意味着,异步
方法都酷似正规的方法,他们正在编后。 .NET运行库没有把他们任何特殊的方式。
I've been reading about the new async await
keyword and it sounds awesome, but there is one key question I haven't been able to find the answer for in any of the intro videos I've watched so far (I also read the whitepaper a while back).
Suppose I have a call to await
in a nested function on the main UI thread. What happens to the thread at this point? Does control go back to the message loop and the UI thread is free to process other inputs?
When the awaited task completes, does the entire stack get pushed onto a message queue, such that control will return through each of those nested functions, or is something else entirely happening here?
And secondly (while I have your attention), I don't really understand why asynchronous methods need to be labeled with async
. Can't any method be executed asynchronously? What if I want to execute a method asynchronously but it doesn't have an async keyword--is there a way to do that simply?
Cheers. :)
Edit: Admittedly if I could get the sample code compiling I could probably just figure that out myself, but for one reason or another I'm running into a block there. What I really want to know is to what extent does a continuation continue... does it freeze the entire call stack, to resume it when the task completes, or does it only go back so far? Does a function itself need to be marked as async in order to support continuation, or (as I asked originally) does it continue the entire call stack?
If it doesn't freeze the entire call stack, what happens when the async await hits a non-async calling function? Does it block there? Wouldn't that defeat the point of await? I hope you can see that I'm missing some understanding here that I hope someone can fill in so I can continue to learn this.
Suppose I have a call to await in a nested function on the main UI thread. What happens to the thread at this point? Does control go back to the message loop and the UI thread is free to process other inputs?
Yes. When you await
an awaitable (such as a Task<TResult>
), the thread's current position within the async
method is captured. It then queues the remainder of the method (the "continuation") to be executed when the awaitable is finished (e.g., when a Task<TResult>
completes).
However, there is an optimization that can take place: if the awaitable is already finished, then await
doesn't have to wait, and it just continues executing the method immediately. This is called the "fast path", described here.
When the awaited task completes, does the entire stack get pushed onto a message queue, such that control will return through each of those nested functions, or is something else entirely happening here?
The thread's current position is pushed onto the UI message queue. The details are a bit more complex: continuations are scheduled on TaskScheduler.FromCurrentSynchronizationContext
unless SynchronizationContext.Current
is null
, in which case they are scheduled on TaskScheduler.Current
. Also, this behavior can be overridden by calling ConfigureAwait(false)
, which always schedules the continuation on the thread pool. Since SynchronizationContext.Current
is a UI SynchronizationContext
for WPF/WinForms/Silverlight, this continuation does get pushed onto the UI message queue.
And secondly (while I have your attention), I don't really understand why asynchronous methods need to be labeled with async. Can't any method be executed asynchronously? What if I want to execute a method asynchronously but it doesn't have an async keyword--is there a way to do that simply?
These are slightly different meanings of the word "asynchronous." The async
keyword enables the await
keyword. In other words, async
methods may await
. Old-fashioned asynchronous delegates (i.e., BeginInvoke
/EndInvoke
) is quite different than async
. Asynchronous delegates execute on a ThreadPool
thread, but async
methods execute on the UI thread (assuming that they are called from a UI context and you don't call ConfigureAwait(false)
).
If you want to have a (non-async
) method run on a ThreadPool
thread, you can do it like this:
await Task.Run(() => MyMethod(..));
What I really want to know is to what extent does a continuation continue... does it freeze the entire call stack, to resume it when the task completes, or does it only go back so far? Does a function itself need to be marked as async in order to support continuation, or (as I asked originally) does it continue the entire call stack?
The current position is captured, and "resumed" when the continuation runs. Any function that uses await
to support continuations must be marked async
.
If you're calling an async
method from a non-async
method, then you must deal with the Task
object directly. This is not normally done. Top-level async
methods may return void
, so there's no reason not to have async
event handlers.
Note that async
is purely a compiler transform. That means that async
methods are exactly like regular methods after they're compiled. The .NET runtime does not treat them in any special way.
这篇关于发生在C#异步CTP的`awaiting`主题是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!