C# BeginInvoke返回什么样的类?如何使用它调用EndInvoke?

C# BeginInvoke返回什么样的类?如何使用它调用EndInvoke?,c#,C#,我正在通过ASP.net自下而上地工作,我正在建立一个旧的学校代理模式: public delegate void ProcessRequestDelegate(HttpContext context); public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { ProcessRequestDelegate asyn

我正在通过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?
    }
但是我意识到,我不知道在
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)
      }