I'm writing a thread pool use C#.
This thread pool needs to support execute different type of function.
Below is what I need:
- bind a function and its arguments into a functor(or say callable object) and its signature should be void(void)
- get a
System.Threading.Tasks< TResult >that represents the return value of our callable package
In CPP, I can do it with some template magic:
template <typename funtype, typename ...argstype>
std::future<typename std::result_of<funtype(argstype...)>::type> async(funtype&& func, argstype&&... args) {
//start function body↓
typedef std::packaged_task<std::result_of<funtype(argstype...)>::type(argstype...)> task_type;
auto task = std::make_shared<task_type>(std::forward<funtype>(func));
// bind to a callable object(functor) with signature void(void)
auto whatINeed= std::bind([task](argstype... args) mutable {
(*task)(std::forward<argstype>(args)...);
}, std::forward<argstype>(args)...);
//and we return the std::future which represents the return value of our package
//in C#, i need to return an Task<TResult>
return task->get_future();
}
In C#, now I wrote:
public Task<TResult> async<TResult>(Delegate func, params object[] args)
{
var stdPromiseXD = new TaskCompletionSource<TResult>();
// the lambda is a callable object with signature void(void)
works.Enqueue(() =>
{
try
{
stdPromiseXD.SetResult((TResult)func.DynamicInvoke(args));
}
catch (Exception ex)
{
stdPromiseXD.SetException(ex);
}
});
// return the Task which equals std::future in CPP
return stdPromiseXD.Task;
}
But this C# version is not good as CPP version. First its does not support non-return function, second the DynamicInvoke method could be significantly slow in some situation.
So can anyone tell me how to bind a function and arguments into a pack in C# more elegant?