[英]Why does BackgroundWorker not need to call EndInvoke when it calls BeginInvoke on a delegate?
[英]What sort of class does BeginInvoke return? How can I use it to call EndInvoke?
我正在通过ASP.net自下而上地工作,并且正在建立一个旧式的委托模式:
public delegate void ProcessRequestDelegate(HttpContext context);
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
ProcessRequestDelegate asyncDelegate = new ProcessRequestDelegate(ProcessRequest);
return asyncDelegate.BeginInvoke(context, cb, extraData);
}
public void EndProcessRequest(IAsyncResult result)
{
//?? profit?
}
但是我意识到,我不知道将IAsyncResult result
转换为EndProcessRequest
函数的方式。 我试过了:
public void EndProcessRequest(IAsyncResult result)
{
// Compiler error because this is dumb
((ProcessRequestDelegate)result).EndInvoke(result);
}
但显然您无法将结果转换为委托。 那么结束调用的正确方法是什么。 更一般地, Delegate.BeginInvoke
返回哪种类?
更新
所以我尝试了一下:
public static void Main()
{
IAsyncResult result = BeginStuff("something", null, null);
IAsyncResult result2 = BeginStuff("something else", null, null);
EndStuff(result);
EndStuff(result2);
Console.ReadLine();
}
static Action<String> act = delegate(String str)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("This seems to work");
Thread.Sleep(TimeSpan.FromSeconds(2));
};
static Action<String> act2 = delegate(String str) { };
public static IAsyncResult BeginStuff(String data, AsyncCallback callback, Object state)
{
return Program.act.BeginInvoke(data, callback, state);
}
public static void EndStuff(IAsyncResult result)
{
// This works fine no matter how many times BeginInvoke is called
Program.act.EndInvoke(result);
// This however will fail, because the delegate that began the invocation
// is not the same as the one that ends it.
Program.act2.EndInvoke(result);
}
而且似乎工作正常。 只要使用同一委托调用BeginInvoke
/ EndInvoke
,运行时就会处理其余的事务(我想这就是IAsyncResult的作用)。 但是,如果尝试结束使用其他委托,则会提醒您不要这样做。
另一个更新
我发现了一种更好的方法:
public void Operation()
{
throw new FaultException<FrieldyError>(new FrieldyError("returned with this error"));
}
public IAsyncResult BeginOperation(AsyncCallback callback, object state)
{
return ((Action)Operation).BeginInvoke(callback, state);
}
public void EndOperation(IAsyncResult result)
{
((Action)Operation).EndInvoke(result);
}
由于您只需要使用相同类型的委托,因此您可以使用现有的委托之一,并且可以正常工作。 无需声明您自己的本地/私人代表。
有用!
对您而言无关紧要的是Delegate.BeginInvoke
返回的具体类是什么,无论接口是什么,它都提供了您需要的所有内容,以等待其完成(使用WaitHandle
或轮询技术[ 示例 ])并调用EndInvoke
。
此外,您还指定了AsyncCallback
参数,您是否只是将EndProcessRequest
传递给该参数?
例如,
this.BeginProcessRequest(
HttpContext.Current,
this.EndProcessRequest,
"My extra data");
评论后编辑:
如果按照注释描述实现IHttpAsyncHandler
,则应该有更少的问题,因为可以将委托实例存储为类的成员。
public class ProcessRequestAsyncHandler ; IHttpAsyncHandler
{
private ProcessRequestDelegate asyncDelegate;
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
asyncDelegate = new ProcessRequestDelegate(ProcessRequest);
return asyncDelegate.BeginInvoke(context, cb, extraData);
}
public void EndProcessRequest(IAsyncResult result)
{
asyncDelegate.EndInvoke(result);
}
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
// Do something long-running
}
}
参考:
您可以将其强制转换为AsyncResult对象。 它包含诸如委托和AsyncState
(您在extraData
传递的对象)之类的extraData
。 要获得您的代表,可以尝试一下
((ProcessRequestDelegate)((AsyncResult)result).AsyncDelegate)).EndInvoke();
AsyncDelegate属性获取调用异步调用的委托。
哦,是的,看来您必须这样做。 您可以执行以下操作:
public void EndProcessRequest(IAsyncResult result)
{
ProcessRequestDelegate del = (ProcessrequestDelegate) result.AsyncState;
object item = del.EndInvoke(result)
}
这篇文章在这里 o。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.