这是我的故事:我有wcf服务。它收到工作要求。每个任务都插入阻塞队列。服务器将定期从此队列中获取项目并完成工作(在不同的线程中完全异步)。在我的"做"服务我需要知道什么时候"我的"任务完成了。像这样:
public bool Do(int input)
{
// 1. Add task to the BlockingCollection queue
// 2. Block this thread from returning and observe/wait til my task is finished
return true;
}
这是我的建议/解决方案:
public bool Do(int input)
{
// 1. Create a ManualResetEvent object
// 2. Add this object to task
// 3. Add task to the BlockingCollection queue
// 4. Block this thread from returning - wait for ManualResetEvent object
return true;
}
因此,将有与任务一样多的ManualResetEvent对象。我将确实有一个同步对象数组。这是我的问题的好方法吗?
或者在我的情况下是否有更好的同步类?喜欢等待和脉冲?
感谢您的帮助,
我很抱歉这个头衔。我不知道如何在标题中提出这个问题。
答案 0 :(得分:2)
你的计划很好,但是我建议你不要用专门的线程来等待工作的完成。从new ManualResetEvent(false)
切换到new SemephoreSlim(0,1)
将允许您使用WaitAsync()
,这将允许您在Do
方法中使用async / await并释放线程以执行其他工作。 (更新:这确实应该是TaskCompletionSource
而不是信号量修正,但我不会更新此示例,请参阅下面的第2部分)
public async Task<bool> Do(int input)
{
using(var completion = new new SemephoreSlim(0,1))
{
var job = new JobTask(input, completion);
_workQueue.Add(job);
await completion.WaitAsync().ConfigureAwait(false);
return job.ResultData;
}
}
private void ProcessingLoop()
{
foreach(var job in _workQueue.GetConsumingEnumerable())
{
job.PerformWork(); //Inside PerformWork there is a _completion.Release(); call.
}
}
要使所有内容自包含,您可以更改SemaphoreSlim
/ TaskCompletionSource
并将其放入作业中,然后只返回作业本身。
public JobTask Do(int input)
{
var job = new JobTask(input);
_workQueue.Add(job);
return job;
}
public class JobTask
{
private readonly int _input;
private readonly TaskCompletionSource<bool> _completionSource;
public JobTask(int input)
{
_input = input;
_completionSource = new TaskCompletionSource<bool>();
}
public void PerformWork()
{
try
{
// Do stuff here with _input.
_completionSource.TrySetResult(true);
}
catch(Exception ex)
{
_completionSource.TrySetException(ex);
}
}
public Task<bool> Work { get { return _completionSource.Task; } }
}