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