C# 检测到线程池工作项已完成/正在等待完成
无论出于何种原因,C# 检测到线程池工作项已完成/正在等待完成,c#,multithreading,asynchronous,concurrency,threadpool,C#,Multithreading,Asynchronous,Concurrency,Threadpool,无论出于何种原因,ThreadPool的QueueWorkItem都不会返回工作项的IAsyncResult或其他句柄,这将允许等待工作项完成。有RegisterWait…方法,但您必须传递WaitHandle并且创建它们的成本很高(请参阅IAsyncResult文档,该文档建议您延迟创建WaitHandle,直到请求为止)。任务并行库将修复这一缺陷,但这需要很长时间才能实现。那么,这种设计有什么问题吗 public class Concurrent<T> { private
ThreadPool
的QueueWorkItem
都不会返回工作项的IAsyncResult
或其他句柄,这将允许等待工作项完成。有RegisterWait…
方法,但您必须传递WaitHandle
并且创建它们的成本很高(请参阅IAsyncResult
文档,该文档建议您延迟创建WaitHandle
,直到请求为止)。任务并行库将修复这一缺陷,但这需要很长时间才能实现。那么,这种设计有什么问题吗
public class Concurrent<T> {
private ManualResetEvent _resetEvent;
private T _result;
public Concurrent(Func<T> f) {
ThreadPool.QueueUserWorkItem(_ => {
_result = f();
if (_resetEvent != null)
_resetEvent.Set();
});
}
public WaitHandle WaitHandle {
get {
if (_resetEvent == null)
_resetEvent = new ManualResetEvent(_result != null);
return _resetEvent;
}
...
公共类并发{
私人手册重置事件_重置事件;
私人T_结果;
公共并发(Func f){
ThreadPool.QueueUserWorkItem(=>{
_结果=f();
如果(_resetEvent!=null)
_resetEvent.Set();
});
}
公共WaitHandle WaitHandle{
得到{
如果(_resetEvent==null)
_resetEvent=新的ManualResetEvent(_结果!=null);
返回重置事件;
}
...
编辑:
我问了一个问题。嗯,在获取WaitHandle和设置WaitHandle之间有一个竞争条件。你真的想让打电话的人永远等待,如果他们碰巧迟到了一点点吗 您可能应该执行一些适当的锁定,并保留一个“I have finished”标志,这样,如果您在WaitHandle完成后创建它,那么您可以在返回它之前设置它
我个人也会编写一个静态工厂方法,而不仅仅是使用公共构造函数——或者将其设置为“创建然后显式启动”模式。在构造函数中对工作项进行排队让我觉得很奇怪。为什么不使用异步委托,如下所示:
这将使并发过时,不?请注意,我将
\u result!=null
作为参数传递给ManualResetEvent构造函数。(这对结构不起作用,但想法是一样的。)\u result!=null
作为此处的结束标志(当然不是在实际实现中).是的,这里需要明智的锁定。(续…)一个静态的工厂方法不用说,我很少写一个通用的公共构造函数而不需要一个相应的静态方法。不过,我不会首先将构造函数公开。你也应该考虑返回空的方法……如我所说的,<代码>(如果方法抛出异常,这也会很糟糕。)1)并发提供了一个更容易使用的API(我认为);2)并发只是未来的一个子类型,还有其他子类型的工作方式不同(惰性值、承诺);3)(最重要)因为我没有注意到并发可以实现为异步委托上的一个门面。啊,我从一开始就认为这与未来有关:-)。