C# 如何在一个线程中使用.net异步CTP
因此,我最近读了很多关于net Async CTP的书,其中有一句话不断出现:“异步不是关于启动新线程,而是关于多路复用工作”,“没有多线程的异步是同一个想法[作为协作多任务]。你做一个任务一段时间,当它产生控制时,你在该线程上做另一个任务一段时间” 我试图理解这样的评论是否纯粹(嗯,大部分是)深奥和学术性的,或者是否有一些我忽略的语言结构允许我通过“等待”启动的任务在UI线程上神奇地运行 Eric Lippert在他的博客中给出了这个示例,演示了如何在不使用多线程的情况下使用Asynchrony:C# 如何在一个线程中使用.net异步CTP,c#,asynchronous,tap,ctp,C#,Asynchronous,Tap,Ctp,因此,我最近读了很多关于net Async CTP的书,其中有一句话不断出现:“异步不是关于启动新线程,而是关于多路复用工作”,“没有多线程的异步是同一个想法[作为协作多任务]。你做一个任务一段时间,当它产生控制时,你在该线程上做另一个任务一段时间” 我试图理解这样的评论是否纯粹(嗯,大部分是)深奥和学术性的,或者是否有一些我忽略的语言结构允许我通过“等待”启动的任务在UI线程上神奇地运行 Eric Lippert在他的博客中给出了这个示例,演示了如何在不使用多线程的情况下使用Asynchron
async void FrobAll()
{
for(int i = 0; i < 100; ++i)
{
await FrobAsync(i); // somehow get a started task for doing a Frob(i) operation on this thread
}
}
async void FrobAll()
{
对于(int i=0;i<100;++i)
{
wait FrobAsync(i);//以某种方式启动任务,以便在此线程上执行Frob(i)操作
}
}
现在,我在这里感兴趣的是一条评论:“…开始一项任务,在这个线程上执行Frob(i)操作”
这怎么可能呢?这主要是理论上的评论吗?到目前为止,我看到的唯一一个任务似乎不需要单独的线程的情况(好吧,除非检查代码,否则无法确定)是类似task.Delay()的东西,可以在不启动另一个线程的情况下等待它。但我认为这是一个特殊的情况,因为我没有编写代码。
对于那些希望从GUI线程中卸载自己的一些长时间运行的代码的普通用户,我们不是主要在讨论像Task.Run这样的操作来卸载我们的工作,而这不是在另一个线程中启动它吗?如果是这样的话,为什么要对不将Asynchrony与多线程混淆而袖手旁观呢?请参阅我的
在CPU工作的情况下,您必须使用类似于Task.Run
的方法在另一个线程中执行它。然而,还有很多工作不是CPU工作(网络请求、文件系统请求、计时器等等),并且每一项都可以封装在任务中,而无需使用线程
请记住,在驱动程序级别,一切都是异步的。同步Win32 API只是方便的包装。请参阅我的
在CPU工作的情况下,您必须使用类似于Task.Run
的方法在另一个线程中执行它。然而,还有很多工作不是CPU工作(网络请求、文件系统请求、计时器等等),并且每一项都可以封装在任务中,而无需使用线程
请记住,在驱动程序级别,一切都是异步的。同步Win32 API只是方便的包装。不是100%确定,但从文章中可以看出,它允许windows消息(调整大小事件、鼠标单击等)在调用FrobAsync
之间交错。大致类似于:
void FrobAll()
{
for(int i = 0; i < 100; ++i)
{
FrobAsync(i); // somehow get a started task for doing a Frob(i) operation on this thread
System.Windows.Forms.Application.DoEvents();
}
}
没有每次迭代之间对DoEvents
的讨厌调用。发生这种情况的原因是,调用wait会发送一条Windows消息,该消息将FrobAsync
调用排队,允许在下一次蛙跳开始之前执行蛙跳之间发生的任何Windows消息。不是100%确定,但从文章中可以看出,这似乎是在允许Windows消息(调整事件大小、鼠标单击等)在调用FrobAsync
之间交错。大致类似于:
void FrobAll()
{
for(int i = 0; i < 100; ++i)
{
FrobAsync(i); // somehow get a started task for doing a Frob(i) operation on this thread
System.Windows.Forms.Application.DoEvents();
}
}
在每次迭代之间,如果没有对的恶意调用,则会发生事件。发生这种情况的原因是,对wait的调用会发送一条Windows消息,使FrobAsync
调用排队,从而允许在下一次蛙跳开始之前执行蛙跳之间发生的任何Windows消息。异步t
只是关于异步的。从调用方的角度来看,是否使用多个线程并不重要——只是它执行异步操作。例如,IO完成端口是异步的,但不执行任何多线程操作(操作的完成发生在后台线程上;但是“工作”没有在那个线程上完成)
从wait
关键字来看,“多线程”毫无意义。异步操作所做的是一个实现细节
根据Eric的示例,该方法可以实现如下:
return Task.Factory.StartNew(SomeMethod,
TaskScheduler.FromCurrentSynchronizationContext());
这实际上意味着在当前线程上对SomeMethod
的调用完成所有当前排队的工作后进行排队。这与FrobAsync
的调用方是异步的,因为FrobAsync
很可能在执行SomeMethod
之前返回
现在,FrobAsync
可以实现为使用多线程,在这种情况下,它可以这样编写:
return Task.Factory.StartNew(SomeMethod);
如果默认的TaskScheduler没有更改,那么它将使用线程池。但是,从调用者的角度来看,没有任何变化——您仍然等待该方法
从多线程的角度来看,这是您应该看到的。使用Task.Start
、Task.Run
、或Task.Factory.StartNew
/wait
只是关于异步。从调用方来看,无论是否使用多个线程,都是简单的例如,IO完成端口是异步的,但不执行任何多线程(操作的完成发生在后台线程上;但“工作”没有在该线程上完成)
从wait
关键字来看,“多线程”毫无意义。异步操作所做的是一个实现细节
根据Eric的示例,该方法可以实现如下:
return Task.Factory.StartNew(SomeMethod,
TaskScheduler.FromCurrentSynchronizationContext());
这实际上意味着在当前线程上对SomeMethod
的调用进行排队,当它完成所有任务时