Подтвердить что ты не робот

Coroutines в С#

Я рассматриваю способы реализации совлокальных подпрограмм (пользовательских потоков) в С#. При использовании С++ я использовал волокна. Я вижу, что в интернет-волокнах нет на С#. Я хотел бы получить аналогичную функциональность.

Есть ли какой-либо "правильный" способ реализовать сопрограммы в С#?

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

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

4b9b3361

Ответ 2

Я считаю, что с новым .NET 4.5\С# 5 шаблон async\await должен соответствовать вашим потребностям.

async Task<string> DownloadDocument(Uri uri)
{  
  var webClient = new WebClient();
  var doc = await webClient.DownloadStringTaskAsync(url);
  // do some more async work  
  return doc;  
}  

Я предлагаю посмотреть http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DEV411 для получения дополнительной информации. Это отличная презентация.

Также http://msdn.microsoft.com/en-us/vstudio/gg316360 содержит отличную информацию.

Если вы используете старую версию .NET, для Ascc CTP доступен более старый .NET с живой лицензией go, чтобы вы могли использовать его в производственных средах. Вот ссылка на CTP http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=9983

Если вам не нравится какой-либо из вышеперечисленных вариантов, я считаю, что вы можете следовать шаблону асинхронного итератора, как описано здесь. http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=9983

Ответ 3

Здесь приведен пример использования потоков для реализации сопрограмм:

Так что я обманываю. Я использую потоки, но я только пусть один из них работает одновременно. Когда я создать сопрограмму, создать поток, и затем выполните какое-то рукопожатие, которое заканчивается с вызовом Monitor.Wait(), который блокирует резьбу coroutine - это не будет работать до тех пор, пока не разблокируется. когда его время, чтобы позвонить в сопрограмму, Я выполняю передачу обслуживания, которая заканчивается вызывающий поток заблокирован, и Выполняемая резьба coroutine. Такой же передачи обслуживания на обратном пути.

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

Ответ 4

Вам может быть интересно this - это библиотека, которая скрывает использование сопрограмм. Например, чтобы прочитать файл:

//Prepare the file stream
FileStream sourceStream = File.Open("myFile.bin", FileMode.OpenOrCreate);
sourceStream.Seek(0, SeekOrigin.End);

//Invoke the task
yield return InvokeTaskAndWait(sourceStream.WriteAsync(result, 0, result.Length));

//Close the stream
sourceStream.Close();

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

//Given the signature
//IEnumerable<string> ReadText(string path);

var result = new Container();
yield return InvokeLocalAndWait(() => _globalPathProvider.ReadText(path), container);
var data = container.RawData as string;