是否可以将委托的执行从一个线程移动到另一个中间执行?

时间:2011-08-09 01:27:29

标签: c# .net multithreading asynchronous

有没有什么方法可以抽象出特定委托可以执行的线程,这样我最初可以在调用线程上执行它,但如果最终花费的时间超过一定数量,则将执行移动到后台线程时间?

假设委托被编写为异步。我不是试图采用同步块并将它们移动到后台线程来增加并行性,而是希望通过避免线程开销来简化操作来提高异步执行的性能。

基本上我想知道是否有任何方式可以暂停执行委托或lambda,移动到另一个线程并恢复,如果我可以建立清晰的堆栈边界等等。

我怀疑这是可能的,我只是好奇。

3 个答案:

答案 0 :(得分:3)

这是可能的,但要做到这一点会很尴尬和困难。实现这一目标的最佳方法是使用coroutines。 .NET中唯一符合协程范式的机制是C#的迭代器,它通过yield return关键字。你可能理论上将某些东西混在一起,允许执行一个方法从一个线程转换到另一个 1 。然而,这不过是一个值得讨论的博客,但我认为这是可能的。 2

下一个最佳选择是继续升级到Async CTP。这是一个将在C#中提供的功能,它将允许您完全按照您的要求进行操作。使用提议的await关键字和一些聪明的漏洞也会优雅地实现这一点。最终结果看起来就像下面这样。

public async void SomeMethod()
{ 
  // Do stuff on the calling thread. 

  await ThreadPool.SwitchTo(); // Switch to the ThreadPool.

  // Do stuff on a ThreadPool thread now!

  await MyForm.Dispatcher.SwitchTo(); // Switch to the UI thread.

  // Do stuff on the UI thread now!
}

这只是您使用新await关键字可以执行的许多邪恶酷炫技巧之一。


1 实际将代码执行注入现有线程的唯一方法是,目标是专门设计为以工作项的形式接受注入。

2 您可以看到我的回答here,尝试使用迭代器模仿await关键字。 MindTouch Dream框架是另一种可能更好的变体。关键是应该可以通过一些巧妙的黑客攻击来切换线程。

答案 1 :(得分:2)

不容易。

如果将委托构建为状态机,则可以跟踪状态之间的执行时间,并在达到所需阈值时,在新线程中启动下一个状态。

更简单的解决方案是在新线程中启动它。有什么理由不被接受吗?

(从我的手机发布 - 如果有必要,我会在真正的键盘上提供一些伪代码)

答案 2 :(得分:1)

不,我不认为这是可能的。至少不直接与常规代表。如果你创建了某种IEnumerable,经过一些工作后会产生,那么你可以手动运行它的几次迭代,然后在经过这么多次迭代后切换到在后台线程上运行它。

ThreadPool和TPL的任务应该具有足够的性能,只需在后台线程上运行它。除非你有一个特定的基准测试表明使用一个任务会导致一堆开销,所以听起来你正试图过早地进行优化。