2016-04-15 4 views
10

Хорошо, я надеюсь, что у меня есть основы асинхронного/ждут, но все-таки некоторые вопросы задерживаются в моей голове.Async/Await VS Task.Run: Когда использовать? Как использовать?

Но теперь это проблема, о которой я говорю. Предположим, что в этом простом примере

static void Main(string[] args) 
{ 

    Method(); 

    Console.WriteLine("Main Thread"); 

    Console.ReadLine(); 

} 

public async static void Method() 

{ 

    await Task.Run(new Action(LongTask)); 

    Console.WriteLine("New Thread"); 

} 

public static void LongTask() 

{ 

    Thread.Sleep(8000); 

    Console.WriteLine("Long Task"); 

} 

Основной поток все еще продолжается, и печатает Main Thread после вызова метода() и встретив ждут в течение 8 секунд.

Таким образом, метод Method() возвращается к вызывающей программе, то есть к основной функции здесь, когда он встречается с ожиданием, сохраняет контекст синхронизации и продолжает выполнять оттуда.

Сначала печатает Main Thread.

Затем по истечении 8 секунд, Long Task, а затем New Thread распечатать.

Эта часть, которую я получил. Мой вопрос в моем приложении:

public IList<createcaseoutput> createCase(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)  
{ 
    ............. 
    SQL.CaseSQL.getCreateCaseParameters(CreateCaseInput, out strSPQuery, out listParam);  
    var AcctLst = rep.ExecuteStoredProcedure<createcaseoutput>(strSPQuery, listParam).ToList(); 

    if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString())) 

    { 
     await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq); 
    } 

    console.writeline("Async called"); 
    return AcctLst;  
} 

public async Task<ilist<savecasesearchoutput>> saveCaseSearch(SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key) 

{ 
    .......................... 
    SQL.CaseSQL.getSaveCaseSearchParameters(SaveCaseSearchInput, case_key, out strSPQuery, out listParam); 

    var AcctLst = await rep.ExecuteStoredProcedureAsync<entities.case.savecasesearchoutput>(strSPQuery, listParam); 

    return AcctLst; 
} 

Здесь также createCase наталкивается ждут и он должен немедленно вернуться правильно и выполнить сам очень следующую строку и печать Async called , прежде чем даже SaveCaseSearch завершается правильно?

Хорошо, если я думаю громко, это может быть control returns to the caller.

Так это, как если бы я обернуть вызов SavCaseSearch внутри другой асинхронном/ожидают метод с именем предположим, что

async DoWork() {.... 
} 

и называют это DoWork() из CreateCase() непосредственно так, то

It will go on printing "Async called" once call to DoWork() encounters await and before it even completes ?

Могу ли я думать правильно?

Также иногда я вижу и запутаться между

await someAsync() 

и

await Task.Run(() => someAsync()) ..

какая разница между ними? и какой из них следует соблюдать?

+1

Если вы пытаетесь использовать 'async' в консольном приложении, вы можете столкнуться с проблемами, если вы не настроите их правильно, возможно, это не так, как ожидалось. См. Http://anthonysteele.co.uk/async-and-await-with-console-apps и http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx –

+0

' async' [не о потоках] (http://stackoverflow.com/q/17661428/11683). – GSerg

+0

Ознакомьтесь с сообщением Стивена Клири об этом. Очень полезно – Ian

ответ

4

Мой вопрос в моем приложении:

Ваш код не будет компилироваться, потому что вы используете await без async. Исправленный код будет:

public async Task<IList<createcaseoutput>> createCaseAsync(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)  
{ 
    ... 
    await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq); 
    console.writeline("Async called"); 
    return AcctLst;  
} 

Здесь также createCase наталкивается ждут, и он должен вернуться сразу направо и выполнить сам и печать Async очень следующей строке вызывается перед даже SaveCaseSearch завершается правильно?

No. Этот код:

await saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq); 

такой же, как этот код:

var saveTask = saveCaseSearchAsync(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq); 
    await saveTask; 

Итак, первое, createCaseAsync бы назвать saveCaseSearchAsync. Предположительно, saveCaseSearchAsync выполняет некоторую асинхронную операцию, поэтому возвращает неполную задачу в createCaseAsync. createCaseAsync then await Эта задача, которая заставляет ее возвращать неполную задачу ее вызывающим абонентам.

В конце концов, будет завершено выполнение saveCaseSearchAsync, которое завершит выполнение задачи (которую я назвал saveTask в коде выше). Это, в свою очередь, продолжит выполнение createCaseAsync, и оно перейдет к следующей строке и выведет на консоли «Async called».

Так это, как если бы я обернуть вызов SavCaseSearch внутри другого асинхронном/ждать метод

Вы не нуждались бы в обертку, потому что createCaseAsync уже возвращает Task.

В чем разница между ними? и какой из них следует соблюдать?

Task.Run предназначен, главным образом, для толкания блокирующих работ с нити пользовательского интерфейса и на пул потоков. Поскольку вы находитесь на ASP.NET, не используйте Task.Run.

1

Что касается разницы между асинхронным/ждем и задачи ...

Асинхронных/Await являются синтаксическими ключевыми словами, чтобы упростить код, как все, прежде чем Await ключевых слова происходят в вызывающем потоке и все, от ожидание вперед происходит в продолжении задачи.

Для этого при выполнении задач с использованием TPL потребуется много кода и удобочитаемости. Однако обратите внимание, что под ним все еще используются задачи и продолжения.

Кроме того, они не всегда могут быть использованы вместо задач, как, когда завершение Task недетерминировано, или если у вас есть несколько уровней задач наряду с использованием TaskCompletionSource.

Для получения более подробной информации читайте главу 4 «Asynchronous Programming» в книге «Writing High-Performance .NET Code» Бен Уотсон

Отметим также, Внутренне TPL использует .NET пул потоков, но делает это более разумно, выполнив несколько задач в одном и том же потоке, прежде чем возвращать поток обратно в пул. Это можно сделать с помощью интеллектуального использования объектов-делегатов.

1

Здесь также создается createCase, и он должен немедленно вернуться прямо и выполнить самую следующую строку и распечатать вызов Async до того, как даже SaveCaseSearch завершит работу правильно?

Этого даже не следует компилировать. Оператор «ожидание» может использоваться только в методе «асинхронный». Тем не менее, если вы удалите оператор «ожидание», следующая строка будет печатать «Async called» до того, как завершится даже saveCaseSearch.

Думаю ли я правильно?

saveCaseSearch - это уже метод «асинхронный», поэтому вам не нужно обертывать его для достижения желаемого результата. Тем не менее, вы можете обернуть его другим способом, если хотите.

В чем разница между ними? и какой из них следует соблюдать?

Оператор «ждут» ждет объекта «Задача», так что любой из них в порядке. Я бы выбрал await someAsync(), потому что это меньше кода для написания.

3

Первое правило async - всегда использовать async или никогда не использовать async.

Если ваш базовый API не может обрабатывать async, использовать async в верхних слоях (например, ASP.NET MVC) бесполезно, поскольку в какой-то момент вы получите головоломку потока, поскольку все потоки заняты ожиданием операций ввода-вывода (например, вызовы БД).

Ваш пример - классический случай, когда вы смешиваете синхронизацию и асинхронный режим. Звонок Sleep блокирует поток до его завершения. Вы должны были использовать Task.Delay, так как он выпустил бы поток до тех пор, пока не завершится задержка.

Мой совет - просто начать с правила, которое я упомянул первым, и только когда связаны операции привязки IO, такие как DB или вызовы файлов. Затем, когда вы лучше понимаете async, вы можете начать разорвать его, поскольку у вас есть гораздо лучшее понимание того, к чему это может привести.

(Извините, что не отвечал на ваши вопросы напрямую, но нарезка представляет собой сложную тему, и ваш мозг может поджарить, если вы попытаетесь получить все это напрямую. Начните с малого.)