C# IAsyncResult

C# IAsyncResult,c#,C#,为什么IAsyncResult要求我保留对开始调用它的代理的引用 我希望能够写出以下内容: new GenericDelegate(DoSomething).BeginInvoke(DoSomethingComplete); void DoSomethingComplete(IAsyncResult ar) { ar.EndInvoke(); } IAsyncResult是一个非常。。。过度使用的接口。要在如此多的场景中成为一个可用的接口,它只能真正拥有适用于所有使用它的场景的属性和

为什么IAsyncResult要求我保留对开始调用它的代理的引用

我希望能够写出以下内容:

new GenericDelegate(DoSomething).BeginInvoke(DoSomethingComplete);

void DoSomethingComplete(IAsyncResult ar)
{
    ar.EndInvoke();
}

IAsyncResult是一个非常。。。过度使用的接口。要在如此多的场景中成为一个可用的接口,它只能真正拥有适用于所有使用它的场景的属性和字段。否则,API将很难提供不符合其特定需求的参数

只有在一部分情况下,才会为委托创建IAsyncResult。其他场景(如Control.BeginInvoke)不以委托开始,如果存在委托,则无法向接口属性提供委托


IAsyncResult在这里采用了极简主义的方法,并且只有它的所有用途都能提供的属性

尝试将委托作为异步状态参数传递,例如

class Program {
    static void Main(string[] args) {
        Action d = delegate {
            Console.WriteLine("From the delegate");
        };
        var e = new ManualResetEvent(false);
        d.BeginInvoke(r => {
            ((Action)r.AsyncState).EndInvoke(r);
            e.Set();
        }, d);
        e.WaitOne();
    }
}

我发现整个开始/结束模式不必要地复杂——因此我(与F#使用的模式非常相似)。结果:不再需要保留代理(etc)。

在执行正常1代理
开始激活时,您不需要保留自己对代理的引用;您可以将
IAsyncResult
强制转换为
AsyncResult
并从
AsyncDelegate
属性中检索委托。在任何人说“这是一个肮脏的黑客”之前

AsyncResult类与使用委托进行的异步方法调用结合使用。从委托的BeginInvoke方法返回的IAsyncResult可以强制转换为AsyncResult。AsyncResult具有AsyncDelegate属性,该属性保存调用异步调用的委托对象

所以你可以写:

new GenericDelegate(DoSomething).BeginInvoke(DoSomethingComplete);

void DoSomethingComplete(IAsyncResult ar)
{
    ((GenericDelegate)((AsyncResult)ar).AsyncDelegate)).EndInvoke();
}
请注意,您仍然需要知道原始委托的类型(或者至少,我还没有找到绕过此限制的方法;然后我也没有尝试)



1这里的“正常”是指使用编译器生成的方法对委托实例执行
BeginInvoke
。当使用预定义方法时,即当使用声明自己的
BeginX/EndX
方法的类时,这种强制转换为
AsyncResult
的技术不能保证有效。这是因为该类可能在内部执行一些更聪明的操作,例如阻塞IO完成端口,因此可能使用不同类型的
IAsyncResult
。但是,在假设的场景中,它可以很好地工作。

+1-我不确定它是否能简化与普通代理的工作(请参阅我的答案了解原因),但我喜欢它也能与预定义的BeginX/EndX方法一起工作。FTW!捕获“d”更简单:d.BeginInvoke(r=>{d.EndInvoke(r);…},null);[根据上面链接的博文]。