纤程 vs 异步等待

18

我加入了一个C#项目,开发人员在其中大量使用Fibers。在这个项目之前,我甚至都没有听说过它们,并且以前使用async awaitThreadsBackgroundWorker来进行我的多任务操作。今天我问他们为什么使用Fiber,主要的开发人员说这样更容易调试。这意味着他知道特定函数来自哪个线程,甚至可以访问堆栈中更高层次的变量。

我想知道使用Fiber相比使用新的async await和使用Thread的优缺点是什么。

PS:我们使用的是.NET 4.5。


3
你所指的Fiber实现是指使用哪种?是Windows Fiber API吗? - timmyl
1
暂停调试器时确实看不到应用程序的操作,因为大多数情况下所有线程都在空闲。这是异步IO的一个很大的缺点。尽管如此,我也不会推荐使用纤程。 - usr
1
纤程比任务更昂贵。纤程需要1MB的内存用于堆栈。任务需要内存用于本地变量,但它们使用调度程序的堆栈。 - Raymond Chen
@timmyl 很抱歉回复晚了。它是使用 Enumarables 手动实现的。 - Alireza Noori
在这种情况下,由于不是操作系统级别的Fibers,我能想到的一个情况是严格的内存占用限制,因此您希望应用程序在一个线程+正常的CLR基础结构线程上运行。使用枚举器的协作式多任务处理是实现这一目标的一种方式。话虽如此,这需要大量的工作。我认为你需要有一个很好的理由去选择这条路,因为CLR线程池和异步I/O非常强大。如果您能提供有关您正在使用的系统类型和任何特殊约束的更多上下文信息,可能会有所帮助。 - timmyl
1个回答

18
我问他们为什么使用Fibers,主要开发人员说这对他来说更容易调试。这意味着他知道特定函数来自哪个线程,甚至可以访问堆栈中更高的变量。
听起来很奇怪。当使用除默认的ThreadPoolTaskScheduler以外的自定义调度程序与任务并行库时,您可以自己决定如何调度任务(不一定是在新线程上)。另一方面,async-await提供了一种方便的方式来执行异步IO操作。VS使您能够调试异步代码,就像执行同步代码一样。
为了使用fibers,需要调用非托管API,因为.NET在BCL中没有提供任何托管包装器。即使fibers文档明确表示使用它们没有明显的优势
总的来说,fibers不能提供比良好设计的多线程应用程序更大的优势。但是,使用fibers可以更轻松地移植设计为调度自己线程的应用程序。
我想知道使用Fibers与使用新的async await和Threads的优缺点是什么。
使用async-await使您能够在感觉像同步执行的同时执行IO绑定的异步工作。任务并行库提供了一种在专用线程上调度工作的简单方法,无论是线程池线程还是新线程,同时允许您钩取调度这些工作单位的机制。我认为今天使用fibers没有任何优势,因为框架已经提供了所有功能。
我认为您应该告诉主要开发人员阅读有关使用任务并行库和async-await的多线程和异步IO工作的文章。我认为这将使您所有人的生活更轻松。

1
感谢您详细的解释,我非常感激。正如您所提到的,我认为光纤技术最大的问题之一就是缺乏 .Net 的支持。 - Alireza Noori
5
额外说明:+1还有一点需要注意,他知道特定函数来自哪个线程,并且甚至可以访问堆栈中更高的变量。 我理解这意味着当恢复时,纤程保留其调用堆栈,而异步方法则不会。我认为总体上,使用async/await/TPL更容易使用和理解,但是我能够理解反对它们的调用堆栈调试论点。 - Stephen Cleary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接