Как написать C # 5 асинхронно? - PullRequest
3 голосов
/ 27 мая 2011

У меня следующий сценарий:
Когда вводится команда (для теста, это консольное приложение, когда оно готово, я надеюсь, что это будет WebService), я выполняю некоторый код, и когда требуется дальнейший ввод данных пользователемЯ немедленно возвращаюсь к интерпретатору команд.Когда дается новый ввод, я хочу возобновить обработку с того места, где я его оставил.Это так похоже на шаблон асинхронного ожидания c # 5, что я решил попробовать.Я думал об этом:

public void CommandParser()
{
   while(true)
   { 
      string s = Console.ReadLine();
      if (s == "do_something")
         Execute();
      else if (s == "give_parameters")
         SetParameters();
      //... 
   }
}
MySettings input;
public async void Execute()
{
  //do stuff here
  MyResult result = null
  if (/*input needed*/){
     input = new MySetting();
     result = await input.Calculate();
  }
  else { /* fill result synchronously*/}
  //do something with result here

}

public void SetParameters()
{
   if (input!=null)
      input.UseThis("something"); //now it can return from await
}

Теперь мой вопрос, как написать MySettings.Calculate и MySettings.UseThis?Как вернуть Задание из первого и как сигнализировать о готовности со второго?Я пробовал много заводских методов для Task, но я не могу найти правильный!Пожалуйста, помогите!

1 Ответ

6 голосов
/ 27 мая 2011

Один из вариантов - использовать TaskCompletionSource<T>. Это создаст задачу для вас, и вы можете вызвать SetResult или SetException на источнике, который будет сигнализировать о задаче соответствующим образом.

Это то, что я использовал для реализации AsyncTaskMethodBuilder<T> для Eduasync - так что вы можете посмотреть на это для примера.

Вам нужно было бы либо заранее настроить TaskCompletionSource, либо выполнить какую-либо другую координацию, чтобы оба input.Calculate и UseThis знали об одном и том же объекте - но тогда Calculate просто вернул бы completionSource.Task, и UseThis будет звонить completionSource.SetResult.

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

...