Soo*_*nts 17 .net c# c#-4.0 async-ctp
我正在评估Async CTP.
如何在另一个线程池的线程上开始执行异步函数?
static async Task Test()
{
// Do something, await something
}
static void Main( string[] args )
{
// Is there more elegant way to write the line below?
var t = TaskEx.Run( () => Test().Wait() );
// Doing much more in this same thread
t.Wait(); // Waiting for much more then just this single task, this is just an example
}
Run Code Online (Sandbox Code Playgroud)
The*_*ung 50
我是新的(我的处女帖子)Stack Overflow,但是我很高兴你问起Async CTP,因为我正在微软的团队中工作:)
我想我明白你的目标是什么,并且有一些你正确的事情,让你到那里.
我想你想要什么:
static async Task Test()
{
// Do something, await something
}
static void Main(string[] args)
{
// In the CTP, use Task.RunEx(...) to run an Async Method or Async Lambda
// on the .NET thread pool
var t = TaskEx.RunEx(Test);
// the above was just shorthand for
var t = TaskEx.RunEx(new Func<Task>(Test));
// because the C# auto-wraps methods into delegates for you.
// Doing much more in this same thread
t.Wait(); // Waiting for much more then just this single task, this is just an example
}
Run Code Online (Sandbox Code Playgroud)
Task.Run与Task.RunEx
由于此CTP安装在.NET 4.0之上,因此我们不想修补mscorlib中的实际 System.Threading.Tasks.Task
类型.相反,操场API在冲突时被命名为FooEx.
我们为什么要说出其中一些Run(...)
和一些RunEx(...)
?原因是由于我们在发布CTP时尚未完成的方法重载的重新设计.在我们当前工作的代码库,我们实际上不得不调整的C#方法重载规则稍微使正确的事情发生了异步lambda表达式-可以返回void
,Task
或Task<T>
.
问题是当异步方法或lambdas返回Task
或者Task<T>
它们实际上在返回表达式中没有外部任务类型时,因为该任务是作为方法或lambda调用的一部分自动生成的.在我们看来,这对于代码清晰度来说似乎是正确的体验,尽管之前确实使事情变得非常不同,因为通常返回语句的表达式可以直接转换为方法或lambda的返回类型.
因此,异步void
lambdas和异步Task
lambdas都支持return;
不带参数.因此需要澄清方法重载决策以决定选择哪一个.因此,您同时拥有Run(...)和RunEx(...)的唯一原因是,在PDC 2010命中时,我们将确保为Async CTP的其他部分提供更高质量的支持.
如何考虑异步方法/ lambdas
我不确定这是否是一个混乱点,但我想我会提到它 - 当你编写异步方法或异步lambda时,它可以承担调用它的任何人的某些特征.这取决于两件事:
等待的CTP设计和我们当前的内部设计都是基于模式的,因此API提供商可以帮助充实您可以"等待"的一系列充满活力的东西.这可能会根据您正在等待的类型而有所不同,其常见类型是Task
.
Task
等待实现是非常合理的,并且按照当前的线程SynchronizationContext
来决定如何推迟工作.如果您已经在WinForms或WPF消息循环中,那么您的延迟执行将返回到同一消息循环(就像您使用BeginInvoke()
"其余方法").如果你等待一个任务并且你已经在.NET线程池中,那么"你的方法的其余部分"将在其中一个线程池线程上恢复(但不一定完全相同),因为它们被合并开始并且您很可能很乐意使用第一个可用的池线程.
关于使用Wait()方法的注意事项
在您使用的样本中:
var t = TaskEx.Run( () => Test().Wait() );
这样做是:
'await'运算符的主要好处是它允许您添加稍后执行的代码 - 但不会阻塞原始线程.在线程池的情况下,您可以实现更好的线程利用率.
如果您对VB或C#的Async CTP有其他疑问,请告诉我,我很想听听他们:)
通常由方法返回Task
以确定它运行的位置,如果它正在开始真正的新工作而不是仅仅捎带其他东西.
在这种情况下,它看起来并不像你真的希望该Test()
方法是异步的 - 至少,你没有使用它是异步的事实.你只是在另一个线程中启动东西...该Test()
方法可以完全同步,你可以使用:
Task task = TaskEx.Run(Test);
// Do stuff
t.Wait();
Run Code Online (Sandbox Code Playgroud)
这不需要任何异步CTP优点.