await AsyncMethod() срещу await await Task.Factory.StartNew‹TResult›(AsyncMethod)

Предвид следния метод:

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 ще се случи незабавно в нова задача в първия случай, но честно казано не разбирам напълно как работят Tasks, async и await и съм доста разбира се, че просто усложнявам нещата за себе си.

РЕДАКТИРАНЕ:

Този въпрос възникна от разглеждането на този пример за 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 и да предам асинхронна функция?


person Justin Lang    schedule 17.07.2012    source източник
comment
Защо искате да го напишете по този начин? Целият смисъл на използването на новите async/await ключови думи беше да не се налага да го правите.   -  person Jeff Mercado    schedule 18.07.2012
comment
Изглежда като лош пример за част от кода   -  person James Manning    schedule 18.07.2012
comment
Току-що погледнах лично и... Уау. Да, този примерен код на официалния Windows SDK е наистина лош! Мисля, че успяха напълно да пропуснат смисъла на async!   -  person Stephen Cleary    schedule 18.07.2012


Отговори (2)


През повечето време добавянето на друг Task не е полезно, но в някои случаи може да бъде.

Разликата е, че ако сте в UI нишката (или нещо подобно) и изпълните DoSomethingAsync() директно, неговата първа част (// do some work) също ще се изпълни в UI нишката, както и всички продължаващи части на метода (освен ако не използват ConfigureAwait()) . От друга страна, ако стартирате друг Task, както първата част, така и всички следващи части на DoSomethingAsync() ще се изпълнят на ThreadPool.

Ако DoSomethingAsync() е написано правилно, добавянето на друго Task не би трябвало да ви дава никакви предимства (и ще ви даде недостатъка от повече режийни разходи), но мога да си представя, че има случаи, в които това ще има значение.

Също така, вместо да използвате Task.Factory.StartNew() и две awaits, можете да напишете:

await Task.Run(DoSomethingAsync);
person svick    schedule 18.07.2012
comment
Добра точка, не се сетих за частта преди чакането... +1 - person Thomas Levesque; 18.07.2012

Да, има разлика: в първата форма имате допълнително ниво на Задача, което не носи абсолютно нищо полезно.

Първата форма е основно еквивалентна на тази:

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

Така че всъщност няма смисъл: вие създавате задача, която просто... създава друга задача.

person Thomas Levesque    schedule 17.07.2012
comment
Благодаря за отговора - и аз така си мислех. Ако имате момент, бихте ли адресирали редакцията ми? Донякъде съм объркан от подхода, възприет в примера, който гледах... - person Justin Lang; 18.07.2012
comment
@justin, съгласен съм с Джеймс, това е наистина лош пример... няма причина да създавате задача на асинхронен метод, тъй като той вече връща задача - person Thomas Levesque; 18.07.2012
comment
Има има разлика между двете (и нямам предвид само режийни), вижте отговора ми. - person svick; 18.07.2012