2011-10-16 14 views
4

我对C#比较陌生,所以请耐心等待。Task.Factory.FromAsync如何工作/行为?

我想了解Task FromAsync的工作方式。

var task1 = Task<int>.Factory.FromAsync(Foo1, ...); //what happens here? Is this 
called on a thread from threadpool? 

SomeCode1(); // <- is this code executed in parallel with Foo1 

task1.ContinueWith(Foo2,...); //does this block the current thread until Foo1 
finishes? Shouldn't it act like a callback? If this whole code runs on a "normal" 
thread does it block it? If this runs on a thread from a thread pool does it 
release the thread until Foo1 finishes? 

SomeCode2(); 

感谢您的帮助,我真的很苦恼与异步编程。

回答

5

FromAsync提供其使用Asynchronous Programming Model (APM)BeginXxxEndXxx方法来创建Task一种方便的机制。

由此产生的Task默认情况下将在线程池线程上执行(并且您的后续调用SomeCode1()确实将在当前线程上执行,并行于Task)。

TaskContinueWith方法确实起到很像一个回调,即提供给此方法的任务后,将执行委托完成,也一些线程池中的线程。它确实不是阻塞当前线程。

事实上,您应该在创建任务时设置此延续,例如,

var task1 = Task<int>.Factory.FromAsync(Foo1, ...).ContinueWith(Foo2,...); 

有关在.NET线程我全力推荐读好文如CLR via C#第五部分更普遍和详细信息。

+10

“默认情况下,结果Task将在线程池线程上执行” - 仅当操作实际需要运行线程时才会执行。例如,I/O操作将使用I/O完成端口而不是线程。由于线程是一个有限且较昂贵的资源,因此这种扩展性更好。 –

+0

@Allon:你提出一个有效的观点,在I/O绑定操作中,大部分工作不会在线程池线程上发生,但即使在这种情况下,是不是Begincxx的_call_和I/O完成端口回调(将调用EndXxx)都发生在线程池线程上? –

+0

对BeginXxx的调用可以由任何线程创建,即使是UI线程也是如此,因为它不会阻塞。该回调将在ThreadPool线程上调用,但较新的编程模型(例如[EAP](http://msdn.microsoft.com/en-us/library/wewwczdw.aspx)和Task/await)可能会运行回调/事件/延续,如果任务是从该线程启动的,则在特定线程(如UI线程)上执行/事件/延续。请参阅'SynchronizationContext'类和'TaskScheduler.FromCurrentSynchronizationContext()'方法的文档。 –