通过c++互操作或其他方式延续c#一流

本文关键字:延续 一流 方式 其他 c++ 互操作 通过 | 更新日期: 2023-09-27 18:19:11

我们有一个非常高性能的多任务,接近实时的c#应用程序。这种性能主要是通过使用自己开发的调度器在内部实现协作多任务来实现的。这通常被称为微线程。在这个系统中,所有的任务都通过队列与其他任务通信。

我们遇到的特殊问题似乎只能通过c#不支持的第一类延续来解决。

具体来说,这个问题出现在处理队列的两种情况下。每当任何特定任务在将项目放入队列之前执行一些工作时。如果队列已经满了怎么办?

相反,另一个任务可能做了一些工作,然后需要从队列中取出一个项目。如果队列是空的呢?

我们已经在90%的情况下解决了这个问题,通过将队列链接到任务,以避免任务在任何出站队列已满或入站队列为空时被调用。

此外,某些任务被转换为状态机,以便它们可以处理队列是否满或空,并且无需等待即可继续。

真正的问题出现在一些极端情况下,其中任何一种解决方案都是不切实际的。这种情况下的想法是保存当前的堆栈状态,然后切换到另一个任务,这样它就可以完成工作,然后在能够继续的时候重试等待的任务。

在过去,我们尝试将等待任务回调到调度中(递归地),以允许其他任务稍后重试等待任务。然而,这导致了太多的"死锁"情况。

有一个自定义CLR主机的例子,它使。net线程实际上作为"纤维"运行,本质上允许在线程之间切换堆栈状态。但现在我似乎找不到任何示例代码。另外,要想正确使用它,似乎需要一些相当复杂的东西。

有没有人有其他创造性的想法,如何有效地在任务之间切换,避免上述问题?

是否有其他CLR主机提供此功能,商业或其他?是否有任何附加的本机库可以提供c#的某种形式的延续?

通过c++互操作或其他方式延续c#一流

有c# 5 CTP,它对用新的async关键字声明的方法执行延续传递样式的转换,当使用await关键字时执行基于延续传递的调用。

这实际上并不是一个新的CLR特性,而是一组用于编译器对代码执行CPS转换的指令,以及一些用于操作和调度延续的库例程。async方法的激活记录放在堆上而不是堆栈上,因此它们不绑定到特定的线程。

不行,不行。c#(甚至是IL)是一种过于复杂的语言,无法以通用的方式执行这种转换(CPS)。你能得到的最好的就是c# 5将提供的。也就是说,您可能无法中断/恢复高阶循环/迭代,这是您真正想要的通用可实现的延续。

由于压力下的问题,从CLR v2中删除了光纤模式,参见:

  • 光纤和CLR
  • 给CLR专家的问题:光纤模式支持

据我所知,纤维支持还没有被重新添加,尽管从阅读上面的文章来看,可能会再次添加(然而,6-7年来没有提到这个话题的事实使我相信这不太可能)。

光纤支持的目的是为使用光纤的现有应用程序(如SQL Server)提供一种方式来托管CLR,从而使它们能够最大限度地提高性能,而不是作为一种方法来允许。net应用程序创建数百个线程- 中的短光纤并不是解决你的问题的灵异方案。然而,如果你有一个使用光纤的应用程序,并且希望托管CLR,那么托管api确实为CLR与你的应用程序"很好地工作"提供了手段。关于这方面的一个很好的信息来源是托管API文档,或者查看SQL Server如何托管CLR,其中有几篇非常翔实的文章。

还可以快速读取线程、光纤、堆栈和地址空间。

实际上,我们已经决定了一个方向。我们使用消息传递的观察者模式。我们建立了一个自己开发的库来处理类似于Erlang进程的"代理"之间的所有通信。稍后,我们将考虑使用AppDomains来更好地分离代理。设计思想借鉴了Erlang编程语言,它具有非常可靠的多核和分布式处理。

您的问题的解决方案是使用无锁算法,允许至少一个任务在系统范围内进行。您需要使用依赖于CPU的内联汇编器来确保原子CAS(比较与交换)。维基百科上有一篇文章以及Douglas Schmidt所著的《面向模式的软件体系结构,并发和网络化对象的模式》一书中描述的模式。我不清楚你将如何在。net框架下做到这一点。

解决这个问题的另一种方法是使用发布-订阅者模式或可能的线程池。

希望这对你有帮助?