Я рекомендую использовать Func<TResult>
и Action
вместо делегата, а затем использовать замыкания в вызывающем коде для упрощения использования. Func - универсальный строго типизированный делегат, который возвращает результат, а Action - универсальный строго типизированный делегат, который не возвращает результат.
public Task<TResult> Enqueue<TResult>(Func<TResult> func)
{
var stdPromiseXD = new TaskCompletionSource<TResult>();
// the lambda is a callable object with signature void(void)
works.Enqueue(() =>
{
try
{
stdPromiseXD.SetResult((TResult)func());
}
catch (Exception ex)
{
stdPromiseXD.SetException(ex);
}
});
// return the Task which equals std::future in CPP
return stdPromiseXD.Task;
}
public Task Enqueue(Action action)
{
return Enqueue<object>(() =>
{
action();
return null;
});
}
Я назвал это с:
var arg1 = "x1";
var arg2 = "2nd";
var arg3 = "third";
var resultTask1 = tp.Enqueue(() => DoConsoleWrite(arg1, arg2, arg3));
var resultTask2 = tp.Enqueue(() => SumAllNumbers(1, 2, 3, 4, 5));
var resultTask3 = tp.Enqueue(() => ThrowException());
while (tp.Pop()) { }
resultTask1.GetAwaiter().GetResult();
var result2 = resultTask2.GetAwaiter().GetResult();
var result3Exception = resultTask3.Exception;
Альтернативой использованию замыканий является создание перегрузок для каждого счетчика параметров функции (Func<TResult>, Func<T1,TResult>, Func<T1,T2,Result>, etc
и Action, Action<T1>, Action<T1,T2>, etc
)