C# BeginInvoke返回什么样的类?如何使用它调用EndInvoke?
我正在通过ASP.net自下而上地工作,我正在建立一个旧的学校代理模式:C# BeginInvoke返回什么样的类?如何使用它调用EndInvoke?,c#,C#,我正在通过ASP.net自下而上地工作,我正在建立一个旧的学校代理模式: public delegate void ProcessRequestDelegate(HttpContext context); public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { ProcessRequestDelegate asyn
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?
}
但是我意识到,我不知道在EndProcessRequest
函数中将IAsyncResult结果
转换为什么。我试过:
public void EndProcessRequest(IAsyncResult result)
{
// Compiler error because this is dumb
((ProcessRequestDelegate)result).EndInvoke(result);
}
但显然,您不能将结果强制转换给代理。那么,结束调用的正确方法是什么呢。更一般地说,委托.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);
}
因为您只需要使用同一类型的委托,所以可以使用一个预先存在的委托,而且效果很好。无需声明您自己的本地/私人委托
有用 您可以将其强制转换为对象。它包含委托和异步状态
(您传入的外部数据
)等属性。要获得您的委托,您可以尝试以下方法
((ProcessRequestDelegate)((AsyncResult)result).AsyncDelegate)).EndInvoke();
属性获取调用异步调用的委托。委托返回的具体类对您来说并不重要。BeginInvoke是什么,无论它是什么,接口都提供了等待其完成所需的一切(使用
WaitHandle
或轮询技术[])并调用EndInvoke
此外,您已经指定了一个AsyncCallback
参数,您是否将EndProcessRequest
传递给该参数
例如
评论后编辑: 如果您正在实现注释中描述的
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
}
}
参考:
- 哦,是的,看来你必须这样做。以下是您可以做的:
public void EndProcessRequest(IAsyncResult result)
{
ProcessRequestDelegate del = (ProcessrequestDelegate) result.AsyncState;
object item = del.EndInvoke(result)
}
阅读本文。我不确定假设返回的对象是AsyncResult是否是一个好主意。可能是实现IAsyncResult接口的其他对象?否则,该方法的签名将声明其返回的AsyncResult。此外,尽管我倾向于同意Petar的观点,即假设开始/结束模式只有一个入口点是不好的做法,因此从技术上来说,假设它将是ProcessRequestDelegate是安全的,尽管我确实认为更通用的解决方案(即适用于所有代理的解决方案)会很酷+尽管如此,这是一个很好的工作解决方案!是的,你们都是对的,在这个例子中,它采用了铸造类型。要使其通用,可以尝试使回调通用。我没有尝试过这个,但是这里有一个例子,您如何跳过显式强制转换来调用
EndInvoke
?我读了这篇文章,但我认为您的第一个答案更正确。我不是构建代理的人,这是IHttpAsyncHandler
接口(用于asp)的一部分,所以我必须遵循它的结构(除非我没有?),所以我认为你更接近你的原始答案。哦,我明白你的意思了。但我没有调用BeginProcessRequest,IIS是。我只是实现开始/结束模式,因为这正是IHTTPassynchandler所需要的。我以前见过这种模式,但我很困惑,将asyncDelegate
设置为某个对象是否会覆盖现有信息?如果我随后调用asyncDelegate.EndInvoke
,这是否意味着我只能结束最近的请求?以前的请求会发生什么变化?很明显,我对这个结构有些不理解。@sircodesalot-您缺少IIS将为它处理的每个请求创建处理程序的新实例。看看代码下面链接的示例-您认为这只会传输最近请求的文件吗?或者两个同时请求可能会将错误的文件传输给错误的用户?(回答:否-IIS将其排序)@sircodesalot-我的错,您需要覆盖IsReusable
并返回false。医生:但如果你必须将IsReusable设置为false,这似乎证实了我的怀疑?如果您必须生成多个实例,当然可以是异步的,但我认为这似乎并不能解决主要问题。非常感谢您的努力,但这不会起作用,因为AsyncState是用户在调用BeginInvoke时提供的“上下文信息”。在上面的示例中,result.AsyncState
将由用户(在本例中为IIS)在extraData
参数中填充的内容填充。
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
}
}
public void EndProcessRequest(IAsyncResult result)
{
ProcessRequestDelegate del = (ProcessrequestDelegate) result.AsyncState;
object item = del.EndInvoke(result)
}