所以C#/ .NET问题。在使用.BeginInvoke异步调用某些方法时,是否总是需要调用.EndInvoke?我在某处读过它是强制性的,但问题是.EndInvoke会阻止执行吗?有某种通用的解决方案吗?
答案 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方法,因为它不依赖于委托类型(通过反射解决)