2

既存のプログラム(内部で作成されたもの)を、元のプログラムとは異なるライブラリを使用するように適合させようとしています。ライブラリ固有のコードのほとんどを抽象化しました(簡単な部分のようです)。

問題は、古いライブラリがブロッキングメソッドを使用して呼び出しを実行し、内部プログラムがブロッキングメソッドが呼び出されることを期待しているのに、新しいライブラリが非同期メソッドを使用することです。

非同期操作が完了するのを待つためのベストプラクティスは何でしょうか。私の最初の考えは、completedというブールフラグを設定し、completed==trueになるまでwhileループでスピンすることでした。

これは、私が利害関係者のためにまとめようとしている概念実証のためのものであり、利害関係者がプロジェクトを承認した場合は、プログラムの問題のある部分を書き直します。しかし、当分の間、非同期呼び出しが完了するまで、関数が非同期メソッドを呼び出すブロックを待つ必要があります

4

3 に答える 3

2

カウントダウンラッチをasyncメソッドに渡し、ラッチを待ちます。asyncメソッドが完了すると、カウントダウンラッチが通知され、実行を続行できます。モニターも原則として使用できますが、waitを呼び出す前に非同期メソッドが完了し、通知を見逃してしまうという残念なケースでは安全ではありません。

ああ、そして.NETの世界では、カウントダウンラッチはCountdownEventと呼ばれています:CountdownEventクラス

于 2010-01-21T15:42:43.480 に答える
2

フラグの代わりに、ミューテックスのようなものを使用したいと思います。

これを行うには、非同期呼び出しが完了すると、そのライブラリに通知するイベントが必要です。次のようになります。

  1. ミューテックスを作成する
  2. 非同期の完全なメソッドで、「myMutex.Release();」を追加します。
  3. メインメソッドで、asyncメソッドを呼び出した後、「myMutex.WaitOne();」を追加します。これにより、非同期呼び出しが完了するまでスレッドがブロックされます。

私がこのようなものを使用してからしばらく経ちましたが、それがどのように機能するかはかなり確信しています。

編集:おっと、私はミューテックスではなく、セマフォを考えていたと思います:

    private static Semaphore mySemaphore = new Semaphore(0, 1);

    static void Main(string[] args)
    {
        Console.WriteLine("Waiting on async call");
        (new Thread(ASyncCallCompleted)).Start();
        mySemaphore.WaitOne();
        Console.WriteLine("Waiting Completed");
    }

    private static void ASyncCallCompleted()
    {
        Thread.Sleep(5000);
        mySemaphore.Release();
    }

編集#2:Thorarinの提案による。このクラスは、.Netで次のような状況を処理するように設計されているようです。

    private static AutoResetEvent mySync = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        Console.WriteLine("Waiting on async call");
        (new Thread(ASyncCallCompleted)).Start();
        mySync.WaitOne();
        Console.WriteLine("Waiting Completed");
        Console.Read();
    }

    private static void ASyncCallCompleted()
    {
        Thread.Sleep(5000);
        mySync.Set();
    }
于 2010-01-21T15:48:08.837 に答える
1

これは、への最大1回の同時呼び出しで機能するはずBlockingCallです。AutoResetEventそれ以外の場合は、どの呼び出しが終了したかを判別するために個別のインスタンスが必要になります。ともかく:

delegate void Callback();

class BlockAsync
{
    AutoResetEvent _waitHandle = new AutoResetEvent(false);

    public void BlockingCall()
    {
        AsyncCall(AsyncCallCompleted);
        _waitHandle.WaitOne();
    }

    void AsyncCall(Callback callback)
    {
        // Example is not actually asynchronous, to demonstrate the solution
        // is free of race conditions.
        callback();
    }

    void AsyncCallCompleted()
    {
        _waitHandle.Set();
    }
}
于 2010-01-21T16:28:46.240 に答える