Я пытаюсь создать рабочий пул, который может принимать в качестве входных данных любой Func<T>
или Action
, возвращать задачу и планировать результат этой задачи в каком-то потоке в будущем.
IЯ знаю, что могу использовать ThreadPool
или Task.Factory
, но я делаю это ради обучения.
Теперь моя реализация ниже полагается на то, что я могу поставить в очередь TaskCompletionSource<T>
, обернув ее в dynamic
внутри TaskWrapper
.Я не чувствую себя комфортно, делая это (поскольку я могу себе представить, что это имеет немалые затраты времени выполнения), но я не знаю никаких альтернатив.
public class WorkerHub
{
private readonly ConcurrentQueue<TaskWrapper> _tasks;
private readonly Timer _timer;
public WorkerHub()
{
_timer = new Timer();
_tasks = new ConcurrentQueue<TaskWrapper>();
}
public Task<TResult> Post<TResult>(Func<TResult> func)
{
var cts = new TaskCompletionSource<TResult>();
var wrapper = new TaskWrapper {CompletionSource = cts, Function = func};
_tasks.Enqueue(wrapper);
return cts.Task;
}
public Task Post(Action action)
{
var cts = new TaskCompletionSource<bool>();
var wrapper = new TaskWrapper {CompletionSource = cts, Function = action, isVoid = true};
_tasks.Enqueue(wrapper);
return cts.Task;
}
private TaskWrapper Pop()
{
_tasks.TryDequeue(out var wrapper);
return wrapper;
}
public void Start()
{
_timer.Enabled = true;
_timer.AutoReset = true;
_timer.Interval = 2500;
_timer.Elapsed += (sender, args) =>
{
var wrapper = Pop();
if (wrapper != null) wrapper.CompletionSource.SetResult(wrapper.isVoid ? true : wrapper.Function());
};
_timer.Start();
}
public void Stop()
{
}
private class TaskWrapper
{
public bool isVoid { get; set; }
public dynamic Function { get; set; }
public dynamic CompletionSource { get; set; }
}
Что такое «правильный» способ существованияв состоянии связать с различными типами источников завершения и различными типами функций ввода в одной коллекции?