我目前正在做一个项目,我需要排队处理一些作业,这是要求:
- 必须一次处理一个作业
- 排队的项目必须能够等待
所以我想要类似于:
Task<result> QueueJob(params here)
{
/// Queue the job and somehow return a waitable task that will wait until the queued job has been executed and return the result.
}
我试过让后台运行的任务只从队列中取出项目并处理作业,但困难在于从后台任务到方法。
如果需要,我可以采用仅在 QueueJob 方法中请求完成回调的方式,但如果我可以返回一个透明的 Task 以允许您等待要处理的作业(即使队列中有它前面的作业)。
最佳答案
您可能会找到 TaskCompletionSource<T>
很有用,它可以用来创建 Task
恰好在您想要的时候完成。如果将它与 BlockingCollection<T>
结合使用,你会得到你的队列:
class JobProcessor<TInput, TOutput> : IDisposable
{
private readonly Func<TInput, TOutput> m_transform;
// or a custom type instead of Tuple
private readonly
BlockingCollection<Tuple<TInput, TaskCompletionSource<TOutput>>>
m_queue =
new BlockingCollection<Tuple<TInput, TaskCompletionSource<TOutput>>>();
public JobProcessor(Func<TInput, TOutput> transform)
{
m_transform = transform;
Task.Factory.StartNew(ProcessQueue, TaskCreationOptions.LongRunning);
}
private void ProcessQueue()
{
Tuple<TInput, TaskCompletionSource<TOutput>> tuple;
while (m_queue.TryTake(out tuple, Timeout.Infinite))
{
var input = tuple.Item1;
var tcs = tuple.Item2;
try
{
tcs.SetResult(m_transform(input));
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
}
public Task<TOutput> QueueJob(TInput input)
{
var tcs = new TaskCompletionSource<TOutput>();
m_queue.Add(Tuple.Create(input, tcs));
return tcs.Task;
}
public void Dispose()
{
m_queue.CompleteAdding();
}
}
关于c# - TPL 队列处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14929592/