2

所以 C#/.NET 问题。使用 .BeginInvoke 某些方法异步调用时,我是否总是需要调用 .EndInvoke?我在某处读过它是强制性的,但问题是 .EndInvoke 会阻止执行吗?是否有某种通用解决方案?

4

3 回答 3

5

是的,你必须打电话EndInvoke()

但问题是 .EndInvoke 会阻止执行吗?

当您从回调方法调用它时不是,这是正确的模式。

于 2013-04-14T12:16:26.003 回答
1

是的,这是强制性的,原因有两个:
1) 避免可能的资源泄漏
2) 捕获可能已抛出的任何异常

下面是示例代码:

public delegate void DelegateHelper2(..parameters...);
private void ff(..parameters...);{}
DelegateHelper2 myDelegate =  new DelegateHelper2(ff);
// invoke asynchronyously 
IAsyncResult result = myDelegate.BeginInvoke(..parameters..., CallBackEmpty, null);

....
private void CallBackEmpty(IAsyncResult iasync)
{
    if (iasync != null)
    {
        string typeName = "";
        try
        {
            System.Runtime.Remoting.Messaging.AsyncResult aresult =
                (System.Runtime.Remoting.Messaging.AsyncResult)iasync;
            object action1 = aresult.AsyncDelegate;
            Type actionType = action1.GetType();
            typeName = actionType.ToString();

            if (action1 != null)
            {
                //action1.EndInvoke(iasync);
                actionType.InvokeMember("EndInvoke",
                    System.Reflection.BindingFlags.InvokeMethod, null,
                    action1, new object[] { iasync });
            }
        }
        catch (Exception ex)
        {
            string msg = "CallBackEmpty; for type: " + typeName +
                " ;Exception: " + ex.ToString();
            Setup_TraceExceptions(msg);
        }
    }
}
于 2013-04-14T12:15:56.527 回答
0

因此,似乎人们对上面应用的技巧感到困惑。我会解释。这是您的常规解决方案,当使用 .BeginInvoke 生成线程并忘记它时:

private void ff(..parameters...);{}
DelegateHelper2 myDelegate =  new DelegateHelper2(ff);
// invoke asynchronyously 
IAsyncResult result = myDelegate.BeginInvoke(..parameters..., CallBack2, myDelegate);

private void CallBack2(IAsyncResult iasync)
{
    if (iasync != null)
    {
        try
        {
            DelegateHelper2 action1 = (DelegateHelper2)iasync.AsyncState;
            action1.EndInvoke(iasync);
        }
        catch (Exception ex)
        {
            //Trace exeption somehow 
        }
    }
}

存在问题:
1)您需要单独传递callBack delgate和delgate本身
2)如果您经常使用这种模式(以这种方式产生线程),您需要为每个.BeginInvoke编写一个新的CallBack方法,因为它在里面您指的是特定的委托类型(DelegateHelper2)。(我在我的代码中可能有 8 个这样的调用,这将导致 8 个不同的回调方法等。)

上面的例子确实解决了这些问题,通过这种方式:
1)您只传递 CallBack 委托,action1 是从 IAsyncResult 获得的
2)只需要一个 CallBack 方法,因为它不依赖于委托类型(通过反射解决)

于 2013-04-14T13:27:16.627 回答