2014-01-15 3 views
0

Этот пример частично взят из стекаBlocking и асинхронной в ФОС

public async Task MyMethod(string s1,sring s2) 
{ 
    Trace.TraceInformation("info"); 
    //check input 
    if (s1 == null || s2 == null) 
     Trace.TraceInformation("error"); 

    Task<int> longRunningTask = LongRunningOperation(); 
    //indeed you can do independent to the int result work here 

    //and now we call await on the task 
    int result = await longRunningTask; 
    //use the result 
    Console.WriteLine(result); 
} 

public async Task<int> LongRunningOperation() // assume we return an int from this long running operation 
{ 
    await Task.Delay(1000); //1 seconds delay 
    return 1; 
} 

Я хочу MyMethod быть не перекрыт.

1.so это правильно, что до Task<int> longRunningTask = LongRunningOperation(); пользователь заблокирован? Должен ли я запускать вышеуказанную часть кода (отслеживание трассировки и ввода) асинхронно? Если да, то как? есть ли способ сделать это без применения новой реализации асинхронного метода?

2.При мы начинаем:

Task<int> longRunningTask = LongRunningOperation(); 

начинает выполнение LongRunningOperation самостоятельной работы делается на давайте предположим, что главный поток (Thread ID = 1), а затем ждать longRunningOperation достигается.

Теперь, если longRunningOperation еще не закончен и все еще запущен MyMethod() вернется к его вызывающему методу, поэтому основной поток не блокируется. Когда выполняется longRunningOperation, поток из ThreadPool (может быть любым потоком) вернется в MyMethod() в предыдущем состоянии и продолжит выполнение (в этом случае печать результата на консоль).

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

3.Что случается, если исключение выбрасывается во время асинхронного метода?

4.Если включена синхронная реализация, я могу использовать ее? Как?

ответ

3

1. Вы ошиблись в том, где код переустанавливается пользователем.

Все до int result = await longRunningTask; работает в той же теме, что и функция, которая называется MyMethod(, а не вызов Task<int> longRunningTask = LongRunningOperation();.

Если вы хотите синхронная часть функции также выполняться в фоновом потоке обернуть вызов MyMethod в Task.Run(

var myMethodTask = Task.Run(() => MyMethod("foo", "bar")); 

вы затем можете await или все, что нужно на что вернулись задачи.

2. Если longRunningTask завершено к моменту достижения вами await longRunningTask, функция по-прежнему будет продолжать работать в одном потоке и никогда не вернется к вызывающей программе, пока не достигнет конца функции. Когда он достигает конца функции, он возвращается к вызывающему абоненту с Task уже в завершенном состоянии.

Если longRunningTask не было сделано это будет вернуться к абоненту в точке await и возвращает Task, который будет меняться от Running состояния в Completed состояние, когда функция завершается. Когда возвращается await, он использует SynchronizationContext, который был активным, когда задача начала выяснять, какой поток он должен продолжить, над чем работает.Если вы, где в потоке пользовательского интерфейса, когда вы нажмете await, работа продолжит работу on the UI thread, по умолчанию он будет использовать поток ThreadPool для продолжения работы, если не было SynchronizationContext.

3. Если исключение вы видите исключение, когда await longRunningTask возвращает (или возвращает родительскую нить, если вы завернуты функция в Task.Run()

4. Вы должны использовать отдельный метод для синхронной реализации. См. Две записи в блоге Microsoft «Should I expose asynchronous wrappers for synchronous methods?» и «Should I expose synchronous wrappers for asynchronous methods?»