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

同じタイプのデリゲートを使用する必要があるだけなので、既存のもののいずれかを使用でき、それは正常に機能します。独自のローカル/プライベート デリゲートを宣言する必要はありません。

使える!

4

3 に答える 3

3

によって返される具体的なクラスが何であるかは問題ではありません。それが何であれ、その完了を待ち ( aまたはポーリング手法 []Delegate.BeginInvokeを使用して)、 を呼び出すために必要なすべてをインターフェイスが提供します。WaitHandleEndInvoke

さらに、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 に答える