C#中的协同程序

eya*_*yal 40 c# coroutine fiber

我正在寻找在c#中实现协同例程(用户调度线程)的方法.使用c ++时我使用的是光纤.我在互联网上看到C#中不存在光纤.我想获得类似的功能.

有没有"正确"的方法在c#中实现协同程序?

我曾想过使用在调度程序线程上获取单个执行互斥锁+ 1的线程来实现它,该线程为每个协同程序释放这个互斥锁.但这似乎非常昂贵(它强制每个协程之间的上下文切换)

我也看过了yield迭代器的功能,但据我所知,你不能在内部函数中产生(仅在原始的ienumerator函数中).所以这对我有点好处.

Pre*_*gha 12

编辑:你现在可以使用这些:.net中是否有光纤api?

我相信你应该看看.NETReactive Extensions.例如,可以使用迭代器和yield语句来模拟协同程序.

不过,您可能也想阅读这个SO问题.


Aar*_*ack 10

我相信在新的.NET 4.5\C#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;  
}  
Run Code Online (Sandbox Code Playgroud)

我建议查看http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DEV411了解更多信息.这是一个很棒的演讲.

另外http://msdn.microsoft.com/en-us/vstudio/gg316360也有一些很棒的信息.

如果您使用的是旧版本的.NET,则可以使用旧版.NET的Async CTP和实时许可证,以便在生产环境中使用它.这是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


SLa*_*aks 6

以下是使用线程实现协同程序的示例:

所以我作弊.我使用线程,但我只让其中一个运行.当我创建一个协程时,我创建一个线程,然后做一些握手,最后调用Monitor.Wait(),它阻止了协程线程 - 它将不再运行,直到它被解除阻塞.当调用协程时,我做了一个切换,结束时调用线程被阻塞,协程线程可以运行.在回来的路上同样的交接.

与其他实现相比,这些切换有点贵.如果您需要速度,您将需要编写自己的状态机,并避免所有这些上下文切换.(或者你会想要使用光纤感知运行时 - 交换光纤非常便宜.)但是如果你想要富有表现力的代码,我认为协程会有一些承诺.

  • 使用线程的一个限制是(在Winforms和WPF中,我相信)线程`Larry`创建的表单的控件不能被线程`Moe`访问,即使线程`Larry`没有做任何事情形式并将被阻止,直到'Moe`也没有做任何事情.如果两个协同程序可以在同一个OS线程上运行,它们可以共享资源,否则这些资源只能由创建线程使用. (3认同)

nos*_*tio 6

到了 2020 年,C# 发生了很多变化。我发表了一篇关于此主题的文章,Asynchronous coroutines with C# 8.0 and IAsyncEnumerable

在 C# 世界中,它们(协程)已通过Unity 游戏开发平台得到普及,并且 Unity 使用 IEnumerator和 风格的方法yield return来实现这一点。

在 C# 8 之前,不可能在同一个方法中组合awaityield return,因此很难在协程内使用异步。现在,有了编译器对 的支持 IAsyncEnumerable,就可以很自然地完成。