我正在通过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);
}
由于您只需要使用相同类型的委托,您可以使用其中一个预先存在的委托,它可以正常工作。无需声明自己的本地/私人代表。
有用!
答案 0 :(得分:3)
Delegate.BeginInvoke
返回的具体类是什么,无论它是什么,接口提供了等待其完成所需的所有内容(使用WaitHandle
或轮询技术[无关紧要] examples])并致电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
}
}
参考:
答案 1 :(得分:2)
您可以将其转换为AsyncResult对象。这包含您的委托和AsyncState
(您在extraData
中传递的对象)等属性。要获得您的代表,您可以尝试这个
((ProcessRequestDelegate)((AsyncResult)result).AsyncDelegate)).EndInvoke();
AsyncDelegate属性获取调用异步调用的委托。
答案 2 :(得分:0)
哦,是的,似乎你必须这样做。这是你可以做的:
public void EndProcessRequest(IAsyncResult result)
{
ProcessRequestDelegate del = (ProcessrequestDelegate) result.AsyncState;
object item = del.EndInvoke(result)
}
本文中的here。