对于Threadpool线程,.BeginInvoke总是需要.EndInvoke吗?

时间:2013-04-14 12:13:32

标签: c# .net threadpool

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

3 个答案:

答案 0 :(得分:5)

是的,您必须致电EndInvoke()

  

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

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

答案 1 :(得分: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);
        }
    }
}

答案 2 :(得分: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)你需要通过separtely callBack delgate和delgate本身
2)如果您正在使用此模式,(以这种方式生成线程),您需要为每个.BeginInvoke编写一个新的CallBack方法,因为在其中您引用特定的委托类型(DelegateHelper2)。 (我在我的代码中可能有8个这样的调用,这将导致8种不同的CallBack方法等。)

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

相关问题