2

我正在通过 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 resultEndProcessRequest函数中要转换什么。我试过:

    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);
}

由于您只需要使用相同类型的委托,因此您可以使用预先存在的委托之一,它工作正常。无需声明您自己的本地/私人代表。

有用!

4

3 回答 3

3

返回的具体类Delegate.BeginInvoke是什么对您来说并不重要,无论它是什么接口都提供了您等待其完成所需的一切(使用 aWaitHandle或轮询技术 [示例])并调用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
    }
}

参考:

于 2013-03-12T12:21:17.613 回答
2

您可以将其转换为AsyncResult对象。这包含诸如您的委托和AsyncState(您传入的对象extraData)之类的属性。要让你的代表,你可以试试这个

((ProcessRequestDelegate)((AsyncResult)result).AsyncDelegate)).EndInvoke();

AsyncDelegate属性获取调用异步调用的委托

于 2013-03-12T12:20:25.010 回答
0

哦,是的,看来你必须这样做。这是您可以执行的操作:

public void EndProcessRequest(IAsyncResult result)
{
    ProcessRequestDelegate del = (ProcessrequestDelegate) result.AsyncState;
    object item = del.EndInvoke(result)
}

请看这篇文章

于 2013-03-12T12:28:25.180 回答