执行IAsyncResult明确
-
03-07-2019 - |
题
我通常持谨慎态度执行接口的一部分。但是, IAsyncResult
是有点特殊情况下,给予它支持的几种相当不同的使用模式。你怎么经常使用/用看 AsyncState
/AsyncCallback
模式,而不只是打电话 EndInvoke
, 使用 AsyncWaitHandle
, 或投票 IsCompleted
(呸)?
相关的问题: 检测到一个线程池工作项目已经完成/等待完成.
考虑这一类(非常近似的,锁定需要的话):
public class Concurrent<T> {
private ManualResetEvent _resetEvent;
private T _result;
public Concurrent(Func<T> f) {
ThreadPool.QueueUserWorkItem(_ => {
_result = f();
IsCompleted = true;
if (_resetEvent != null)
_resetEvent.Set();
});
}
public WaitHandle WaitHandle {
get {
if (_resetEvent == null)
_resetEvent = new ManualResetEvent(IsCompleted);
return _resetEvent;
}
public bool IsCompleted {get; private set;}
...
它已 WaitHandle
(懒洋洋地创建的,只是作为描述 IAsyncResult
文件)和 IsCompleted
, 但是我没有看到一个明智的行为 AsyncState
({return null;}
?).所以它不会对它实现 IAsyncResult
?注意, Task
在并行扩展图书馆不会实现 IAsyncResult
, 但只 IsCompleted
实现的隐含.
解决方案
- 以我的经验,只是打电话EndInvoke没有任何等待或被叫回来第一次是很少有用的
- 只提供一些回调有时是不够的,因为你的客户可能要等待多个操作一次(WaitAny,WaitAll)
- 我从来没有接受调查IsCompleted,呀!所以,你可以挽救的执行情况IsCompleted,但它如此简单,它不似乎是值得潜在地震惊的你的客户。
因此,合理执行的一异步可调用的方法真的应该提供充分执行IAsyncResult.
顺便说一句,你通常不需要实施IAsyncResult自己,只要的回报是什么回通过委托。BeginInvoke.见执行情况的系统。IO.流。BeginRead的一个例子。
其他提示
好像你有几个问题。让我们单独处理它们
懒洋洋地创建WaitHandle
是的,这是最正确的方法。你应该以线程安全的方式做到这一点,但懒惰就是这样。
但诀窍是处理WaitHandle。 WaitHandle是IDisposable的基础,必须及时处理。 IAsycResult的文档不包括这种情况。最好的方法是在EndInvoke中。 BeginInvoke的文档明确指出,对于每个BeginInvoke,必须有相应的EndInvoke(或BeginRead / EndRead)。这是处理WaitHandle的最佳位置。
如何实施AsyncState?
如果你看一下返回IAsyncResult的标准BCL API,它们中的大多数都采用状态参数。这通常是从AsyncState返回的值(有关示例,请参阅Socket API)。对于任何返回IAsyncResult的API BeginInvoke样式API,包含一个类型为对象的状态变量是一个好习惯。没有必要,但良好的做法。
在状态变量的abscence中,返回null是可以接受的。
IsCompleted API
这将高度依赖于创建IAsyncResult的实现。但是,是的,你应该实现它。