我通常持谨慎态度执行接口的一部分。但是, 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的实现。但是,是的,你应该实现它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top