2013-07-15 2 views
6

Я прочитал Eric lippert's article около async, а также о путаницах людей, имеющих ключевое слово async. он сказал:async - остаться в текущей теме?

он (async) означает «этот метод содержит поток управления, который включает в себя ожидающий асинхронных операций и, следовательно, будет переписаны в компиляторе в продолжение прохождения стиля для того, чтобы асинхронных операций могут возобновить этот метод в нужном месте.»Всего смысл асинхронных методов это то, что вы остаетесь в текущем потоке как можно больше

Я не понимаю этого. Если я выполняю асинхронный метод (Task), и он запускается, он уверенно работает на другом потоке.

Кроме того, если я пишу метод использует await, (IMHO) он освобождает нормальный поток управления, а код переработан похожи «ContinueWith» позже, другой резьбы.

Я тестировал его с (консоли):

/*1*/ public void StartChain() 
/*2*/ { 
/*3*/   var a = FuncA(); 
/*4*/   Console.WriteLine(a.Result); 
/*5*/ } 
/*6*/ 
/*7*/ public async Task <int> FuncA() 
/*8*/ { 
/*9*/   Console.WriteLine("A--" + Thread.CurrentThread.ManagedThreadId); 
/*10*/   var t = await FuncB(); 
/*11*/   Console.WriteLine("B--" + Thread.CurrentThread.ManagedThreadId); 
/*12*/   return t; 
/*13*/ } 
/*14*/ 
/*15*/ public async Task <int> FuncB() 
/*16*/ { 
/*17*/   Console.WriteLine("C--" + Thread.CurrentThread.ManagedThreadId); 
/*18*/   await Task.Delay(2000); 
/*19*/   Console.WriteLine("D--" + Thread.CurrentThread.ManagedThreadId); 
/*20*/   return 999; 
/*21*/ } 
/*22*/ 
/*23*/ void Main() 
/*24*/ { 
/*25*/   StartChain(); 
/*26*/ } 
/*27*/ 

результат:

A--7 
C--7 
D--17   <-----D and B are on different thread 
B--17 
999 

Так что же Эрик в виду, говоря "остаться на текущей теме"?

редактировать 1:

в asp.net она также возвращает идентификатор потока различно.

public async Task<int> FuncA() 
{ 
    Response.Write("<br/>C----" + Thread.CurrentThread.ManagedThreadId); 
    var t = await FuncB(); 
    Response.Write("<br/>D----" + Thread.CurrentThread.ManagedThreadId); 
    return t; 
} 

public async Task<int> FuncB() 
{ 
    Response.Write("<br/>E----" + Thread.CurrentThread.ManagedThreadId); 
    await Task.Delay(2000); 
    Response.Write("<br/>F----" + Thread.CurrentThread.ManagedThreadId); 
    return 999; 
} 



protected async void Page_Load(object sender, EventArgs e) 
{ 
    Response.Write("<br/>A----" + Thread.CurrentThread.ManagedThreadId); 
    var a=await FuncA(); 
    Response.Write("<br/>B----" + Thread.CurrentThread.ManagedThreadId); 

} 

A----8 
C----8 
E----8 
F----9 
D----9 
B----9 

редактировать 2

(после получения ответа)

, кажется, что нить подается только в GUI приложений:. Я запускаю этот код на WinForm

public async Task<int> FuncA() 
     { 
      textBox1.Text +=Environment.NewLine+ "\nC----" + Thread.CurrentThread.ManagedThreadId; 
      var t = await FuncB(); 
      textBox1.Text += Environment.NewLine + "\nD----" + Thread.CurrentThread.ManagedThreadId; 
      return t; 
     } 

     public async Task<int> FuncB() 
     { 
      textBox1.Text += Environment.NewLine + "\nE----" + Thread.CurrentThread.ManagedThreadId; 
      await Task.Delay(2000); 
      textBox1.Text += Environment.NewLine + "\nF----" + Thread.CurrentThread.ManagedThreadId; 
      return 999; 
     } 




     private async void Form1_Load(object sender, EventArgs e) 
     { 
      textBox1.Text += Environment.NewLine + "\nA----" + Thread.CurrentThread.ManagedThreadId; 
      var a = await FuncA(); 
      textBox1.Text += Environment.NewLine + "\nB----" + Thread.CurrentThread.ManagedThreadId; 
     } 

enter image description here

+0

Ссылка на статью, которую вы смущаетесь о –

+0

@downvoter - комментарий был бы полезен. –

+1

Задача, которую вы ожидаете, выполняется в другом потоке. Весь другой код в методе async выполняется в исходном потоке. Await НЕ запускает новую задачу. Это эквивалентно ContinueWith в ORIGINAL thread. Есть несколько блогов, которые обсуждают это. –

ответ

9

Добавлена ​​поддержка async/await, помогающая программистам писать графические интерфейсы, которые не замерзают.Особенно полезен в приложениях Store, и основная причина, по которой он был добавлен в C# v5, WinRT - довольно недружелюбный api, который имеет много методов асинхронной работы.

Сценарий «остаться в той же теме» очень важно в графическом приложении, необходимо, поскольку графический интерфейс не является потокобезопасным. Однако для этого требуется цикл сообщений, единственный способ получить асинхронный код для возобновления в одном потоке. Цикл сообщения является основным решением для producer-consumer problem. Очевидно, что ваша программа не имеет одного, очень похожа на приложение с консольным режимом. Поэтому вы не получаете этого поведения, оно возобновляется в рабочем потоке.

Не проблема, вы на самом деле не необходимо, чтобы возобновить ее в том же потоке, так как консоль в любом случае является потокобезопасной. Ну, в основном, не считая блокировки, которая была добавлена ​​в .NET 4.5 при запросе ввода. Который, конечно, также означает, что у вас нет heckofalot использования для async/await либо, Task работает отлично также.

+0

Немного OT, но я несколько раз наткнулся на это странное силовое взаимодействие с синхронным поведением. Вы знаете, почему они это сделали? –

+1

Не знаю. За этим был большой план, тот же замок был добавлен в ЭЛТ. Есть * много * программистов, которые занимаются тупиком на своих маленьких тестах «Хит любой ключ для продолжения», добавив, что этот замок был ошибкой. –

+1

И был исправлен, удалив его. –

10

терминология "нить" Эрика Липперта упрощается. У меня есть async/await intro в моем блоге, в котором объясняется, как await будет захватывать текущий контекст и использовать его для возобновления метода async.

Если вы находитесь в контексте пользовательского интерфейса, то контекст представляет собой единственный поток пользовательского интерфейса, а метод async будет возобновлен в этом потоке. В противном случае правила немного сложнее. В частности, консольные приложения не предоставляют никакого контекста, поэтому методы async по умолчанию возобновляют в пуле потоков.

+0

ive прочитайте свою статью много раз. (смотри мои последние вопросы асинхронности;) –

+0

Однако статья отвечает на вопрос. :) Еще раз прочитайте раздел о 'SynchronizationContext' и' TaskScheduler'. –

+0

Так что это не тема, которая хранится. (мой реальный вопрос - спасибо за ответ), - но контекст (который мне уже известен.) ...? подтвердите –

19

Если я выполняю асинхронный метод и он запускается, он, безусловно, запускается в другом потоке.

Нет, это обычно пробегает другую ветку. Он не уверенно бегать по другому потоку.

Прекратите думать о потоках на мгновение и подумайте о природе асинхронности. Характер асинхронности:

  • У меня есть рабочий процесс, который я выполняю сейчас.
  • Я не могу действовать в этом рабочем процессе, пока я получить информацию X.
  • Я собираюсь сделать что-то другое, пока я получаю информацию о X.
  • В какой-то момент в будущем, когда у меня есть X, I «Я вернусь туда, где я остановился в своем рабочем процессе, и продолжаю.

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

Это асинхронный расчет, но для этого нужен только один рабочий. Наличие нескольких сотрудников - это особенно удобный способ сделать асинхронность, это не является обязательным требованием.

+0

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

+4

Это не асинхронная операция. Выполнение длинных вычислений - это асинхронная операция, потому что вы не заблокированы от выполнения другой работы во время нее. –

Смежные вопросы