ManualResetEvent 对象数组
Posted
技术标签:
【中文标题】ManualResetEvent 对象数组【英文标题】:Array of ManualResetEvent objects 【发布时间】:2017-02-09 07:34:46 【问题描述】:这是我的故事:我有 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 对象的数量将与要执行的任务一样多。我将真正拥有一组同步对象。这对我的问题有很好的解决方案吗?
或者在我的情况下有更好的同步类吗?像等待和脉搏?
感谢您的帮助,
我很抱歉标题。我不知道如何在标题中提出这个问题。
【问题讨论】:
为每个任务创建一个类State对象并创建一个List你的计划很好,但是我建议不要占用一个专门的线程来等待工作完成。从new ManualResetEvent(false)
切换到new SemephoreSlim(0,1)
将允许您使用WaitAsync()
,这将允许您在Do
方法中使用async/await 并释放线程以执行其他工作。 (更新:这确实应该是 TaskCompletionSource
而不是 Semaphore Slim,但我不会更新此示例,请参阅下面的第二部分)
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;
【讨论】:
谢谢@Scott,但我为什么要“做”异步? “Do”函数只是将一个项目(一个特定的“int”)添加到队列中并返回......仅此而已。服务器定期接受一批任务并“执行”。在“添加到队列”之后,我需要等待这个特定的“id”完成。 我认为Do
并不总是返回true
我认为true
来自已完成的工作,因此您需要与您的旧@987654334 一起完成.WaitOne()
@ 在Do
方法中的旧代码中。如果返回的 bool 不是来自工作作业,只需让它返回 void
。我会以这种方式用一个例子来更新我的答案。
谢谢。我添加了return true
,以便 wcf 客户端可以在服务器上完成工作(针对他的 id)时收到响应。
我没有注意到这是 WCF,您可能想考虑为 WCF 使用双工回调方法,这更适合您等待完成的长时间运行的操作。
哦,我读到了双工,确实这是一种更好的方法。如果是双工 wcf 服务,您的答案会有所不同吗?以上是关于ManualResetEvent 对象数组的主要内容,如果未能解决你的问题,请参考以下文章