2

BeginXxx EndXxx非同期パターンを使用するライブラリがあります(明らかに、次のコードは簡略化されています)。

ILibrary
{
    IAsyncResult BeginAction(string name, AsyncCallback callback, object state);
    int EndAction(IAsyncResult asyncResult, out object state)
}

そのライブラリを使用し、同じパターン自体を実装するクラスを構築しようとしています。

Manager
{
    private ILibrary library;

    public IAsyncResult BeginMultipleActions(IEnumerable<string> names, 
                                             AsyncCallback callback, object state)
    {
        var handles = new List<IAsyncResult>();
        foreach(string name in names)
        {
            var handle = library.BeginAction(name, OnSingleActionCompleted, null);
            handles.Add(handle);
        }
        //???
    }
    public int EndMultipleActions(IAsyncResult asyncResult, out object state)
    {
        //???
    }

    private void OnSingleActionCompleted(IAsyncResult asyncResult)
    {
        //???
    }
}

(ManualResetEventを使用して)いくつかの解決策を試しましたが、コードが非常に醜いことがわかりました。機能(コールバック、待機ハンドルなど)を失うことなくこれを(C#3.5で)行うための最もクリーンな方法は何ですか?

4

2 に答える 2

1

記述しているパターンを正常に実装できるようにするには、BeginMultipleActionsすべての単一アクションが完了した後で、メソッドに渡されたコールバックを呼び出せる必要があります。イベントを使用してそれらを待機すると、スレッドがブロックされるため、非同期呼び出しを行うという唯一の目的が無効になる可能性があります。単一のアクションに渡すコールバックは、すべてのメソッドが完了した時点を把握し、クライアントからメソッドに提供されたコールバックを呼び出すことができる必要がありますBeginMultipleActions。これはあなたのためにそれを行うかもしれないサンプルです(私はそれをテストしていません)。ただし、これはあくまでも入門用であり、完璧には程遠いものです。あなたが取り組まなければならないいくつかのニュアンスがあります。

interface ILibrary
{
    IAsyncResult BeginAction(string name, AsyncCallback callback, object state);
    int EndAction(IAsyncResult asyncResult, out object state);
}

class Manager
{
    private ILibrary library;

    class AsyncCallInfo : IAsyncResult
    {
        public int PendingOps;
        public AsyncCallback Callback { get; set; }
        public object AsyncState { get; set; }

        public WaitHandle AsyncWaitHandle
        {
            // Implement this if needed
            get { throw new NotImplementedException(); }
        }

        public bool CompletedSynchronously
        {
            get { return false; }
        }

        public bool IsCompleted
        {
            get { return PendingOps == 0; }
        }
    }

    public IAsyncResult BeginMultipleActions(IEnumerable<string> names,
                                             AsyncCallback callback, object state)
    {
        var callInfo = new AsyncCallInfo {
            Callback = callback,
            AsyncState = state
        };

        callInfo.PendingOps = names.Count();
        foreach (string name in names)
        {
            library.BeginAction(name, ar => OnSingleActionCompleted(ar, callInfo), null);
        }

        return callInfo;
    }

    public int EndMultipleActions(IAsyncResult asyncResult, out object state)
    {
        // do your stuff
        state = asyncResult.AsyncState;
        return 0;
    }

    private void OnSingleActionCompleted(IAsyncResult asyncResult, AsyncCallInfo callInfo)
    {
        //???
        Interlocked.Decrement(ref callInfo.PendingOps);
        if (callInfo.PendingOps == 0)
        {
            callInfo.Callback(callInfo);
        }
    }
}

Jeffrey Richter の AsyncEnumerator をご覧になることをお勧めします。非同期コードの記述を簡素化し、非同期実装のいくつかのパターンをサポートします - http://msdn.microsoft.com/en-us/magazine/cc546608.aspx

于 2011-09-03T19:40:04.437 に答える
0

start asincronous オペレーションには beginInvok を使用します。コールバックをサポートしています。

もっと詳しく:

http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

于 2011-08-23T11:43:37.547 に答える