等待AsyncMethod()与等待等待等待Task.Factory.StartNew <tresult>(AsyncMethod)</tresult>

时间:2012-07-17 22:50:35

标签: c# asynchronous task async-await

考虑以下方法:

public async Task<MyObject> DoSomethingAsync() {
    // do some work
    await OpenSomeFileAsync();
    return new MyObject();
}

之间是否存在差异:

public async void SomeEventHandler(EventArgs args) {
    var myObject = await await Task.Factory.StartNew<Task<MyObject>>( DoSomethingAsync);
    // do something with myObject
}

public async void SomeEventHandler(EventArgs args) {
    var myObject = await DoSomethingAsync();
    // do something with myObject
}

我认为DoSomethingAsync的“做一些工作”部分会在第一个案例中的新任务中立即发生,但说实话我并不完全理解任务,异步和等待是如何工作的,而我我很确定我只是为自己过度复杂的事情。

编辑:

这个问题来自于查看这个Metro示例: http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782

特别是在MainPage.xaml.cs中,他们有:

var unused = Task.Factory.StartNew(async () => { // some work... });
// unused is of type Task<TResult>

我试图在不使用匿名异步函数的情况下重做它,我开始想知道,为什么不写一个异步方法并等待它,而不是调用StartNew并交出一个异步函数?

2 个答案:

答案 0 :(得分:11)

大多数情况下,添加另一个Task没有用,但在某些情况下,它可能是。

不同之处在于,如果你在UI线程(或类似的东西)并直接执行DoSomethingAsync(),它的第一部分(// do some work)也将在UI线程上执行,所以任何方法的延续部分(除非他们使用ConfigureAwait())。另一方面,如果您开始另一个Task,则DoSomethingAsync()的第一部分和后续部分都将在ThreadPool上执行。

如果DoSomethingAsync()写得正确,添加另一个Task不应该给你带来任何好处(并且会给你带来更多开销的缺点),但我可以想象有些情况会使差异。

此外,您可以写下:

,而不是使用Task.Factory.StartNew()和两个await
await Task.Run(DoSomethingAsync);

答案 1 :(得分:4)

是的,有一点不同:在第一种形式中,你有一个额外的任务级别,这绝对没有任何用处。

第一种形式基本上与此相同:

Task<Task<MyObject>> task1 = Task.Factory.StartNew<Task<MyObject>>( DoSomethingAsync);
Task<MyObject>> task2 = await task1;
var myObject = await task2;

所以它没有意义:你正在创建一个只创建另一个任务的任务。