patterncsharpMinor
Simple dispatcher implementation
Viewed 0 times
implementationsimpledispatcher
Problem
I need a simple dispatcher implementation(invoke methods on one thread from many threads)
once you dispatch method curent thread should wait for results, so I'm thinking about something like this:
I had test it with such code and it seems too work well ...
```
class Program
{
static void Main(string[] args)
{
Func func = (sleep, i) =>
{
CC.WriteLine(i, "\tTask {0} will sleep for {1}, thread {2}", i, sleep, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(sleep);
CC.WriteLine(i, "\tTask {0} woke up", i, sleep);
return i; //return task number
};
var rnd = new Random();
var disp = new Dispatcher();
{
var tasks = Enumerable.Range(0, 10).Select(i =>
Task.Ru
once you dispatch method curent thread should wait for results, so I'm thinking about something like this:
public class Dispatcher
{
private readonly BlockingCollection> runQueue = new BlockingCollection>();
private readonly BlockingCollection resultQueue = new BlockingCollection();
private readonly CancellationTokenSource source = new CancellationTokenSource();
private readonly Task task;
public Dispatcher()
{
Task.Run(() =>
{
using (source)
using (runQueue)
using (resultQueue)
{
Debug.WriteLine("Dispatcher started with thread {0}", Thread.CurrentThread.ManagedThreadId);
while (!source.IsCancellationRequested)
{
var run = runQueue.Take(source.Token);
resultQueue.Add(run.Item1.DynamicInvoke(run.Item2));
}
Debug.WriteLine("Dispatcher ended");
}
});
}
public void Stop()
{
source.Cancel();
}
[MethodImpl(MethodImplOptions.Synchronized)]
public object Invoke(Delegate @delegate, params object[] @params)
{
runQueue.Add(new Tuple(@delegate, @params));
return resultQueue.Take(source.Token);
}
}I had test it with such code and it seems too work well ...
```
class Program
{
static void Main(string[] args)
{
Func func = (sleep, i) =>
{
CC.WriteLine(i, "\tTask {0} will sleep for {1}, thread {2}", i, sleep, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(sleep);
CC.WriteLine(i, "\tTask {0} woke up", i, sleep);
return i; //return task number
};
var rnd = new Random();
var disp = new Dispatcher();
{
var tasks = Enumerable.Range(0, 10).Select(i =>
Task.Ru
Solution
- Because the task within the Dispatcher is a long running task, you should use the option
TaskCreationOptions.LongRunning. Otherwise the operation blocks a thread-pool thread that is usually used for short operations. Alternatively you could also use aThread.
- Instead of using the blocking collection for returning the result, you could use a
TaskCompletionSource. That would change the return value of the methodInvoketoTask. Therfore the calling code could use the async/await-pattern.
- Consider to throw an exception if the
Dispatcherwas stopped andInvokeis called. Otherwise the call blocks forever, right?
Context
StackExchange Code Review Q#134870, answer score: 8
Revisions (0)
No revisions yet.