Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to move execution of a delegate from one thread to another mid-execution?

Is there any way I can abstract away what thread a particular delegate may execute on, such that I could execute it on the calling thread initially, but move execution to a background thread if it ends up taking longer than a certain amount of time?

Assume the delegate is written to be asynchronous. I'm not trying to take synchronous blocks and move them to background threads to increase parallelism, but rather I'm looking to increase performance of asynchronous execution by avoiding the overhead of threads for simple operations.

Basically I'm wondering if there's any way the execution of a delegate or lambda can be paused, moved to another thread and resumed, if I could establish clear stack boundaries, etc.

I doubt this is possible, I'm just curious.

like image 385
devios1 Avatar asked Aug 09 '11 01:08

devios1


3 Answers

It is possible, but it would be awkward and difficult to get right. The best way to make this happen is to use coroutines. The only mechanism in .NET that currently fits the coroutine paradigm is C#'s iterators via the yield return keyword. You could theorectically hack something together that allows the execution of a method to transition from one thread to another1. However, this would be nothing less than a blog worthy hack, but I do think it is possible.2

The next best option is to go ahead and upgrade to the Async CTP. This is a feature that will be available in C# and which will allow you do exactly what you are asking for. This is accomplished elegantly with the proposed await keyword and some clever exploits that will also be included. The end result would look something like the follwing.

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!
}

This is just one of the many wicked cool tricks you can do with the new await keyword.


1The only way you can actually inject the execution of code onto an existing thread is if the target is specifically designed to accept the injection in the form of a work item.

2You can see my answer here for one such attempt at mimicking the await keyword with iterators. The MindTouch Dream framework is another, probably better, variation. The point is that it should be possible to cause the thread switching with some ingenious hacking.

like image 141
Brian Gideon Avatar answered Oct 14 '22 00:10

Brian Gideon


Not easily.

If you structure your delegate as a state machine, you could track execution time between states and, when you reach your desired threshold, launch the next state in a new thread.

A simpler solution would be to launch it in a new thread to start with. Any reason that's not acceptable?

(posting from my phone - I'll provide some pseudocode when I'm at a real keyboard if necessary)

like image 36
3Dave Avatar answered Oct 13 '22 23:10

3Dave


No I don't think that is possible. At least not directly with regular delegates. If you created some kind of IEnumerable that yielded after a little bit of work, then you could manually run a few iterations of it and then switch to running it on a background thread after so many iterations.

The ThreadPool and TPL's Task should be plenty performant, simply always run it on a background thread. Unless you have a specific benchmark showing that using a Task causes a bunch of overhead it sounds like you are trying to prematurely optimize.

like image 45
BrandonAGr Avatar answered Oct 13 '22 23:10

BrandonAGr