2つの非同期メソッドのいずれかが結果を返すのを待っています

AlefSin

非同期プログラミングを扱う際のベストプラクティスに従っているかどうかを知りたいのですが。私が手元にある問題はこれです:私は同時に2つのデバイスと話している。SendMessageAsync(msg)メソッドを使用してメッセージを送信できます両方のデバイスが同時にこのメッセージを受信しましたが、その見返りとして、一方のデバイスのみが応答を送信し、もう一方のデバイスは単に応答しません。

また、メソッドはCancellationToken、タイムアウト後またはその他の理由ですべてをキャンセルできるように、を受け入れる必要があります。

だから私はメッセージを読むためにこのメソッドを書きました:

public async Task<Message> GetMessageAsync(CancellationToken token)
{
    using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token, new CancellationToken(false)))           
    {
        var device1 = Task.Run(async () => { return await GetDevice1Async(cts.Token); });
        var device2 = Task.Run(async () => { return await GetDevice2Async(cts.Token); });

        var response = await Task.WhenAny(device1, device2);

        cts.Cancel(); //Only one device answers, so cancel the other other one

        return response.Result;
    }            
}

私のソリューションがベストプラクティスに従っているのかどうか疑問に思いました。具体的には、非常に優れたパフォーマンスを実現したいと考えています(私が話しているデバイスはUSBデバイスなので、迅速にサービスを提供できるようにしたいと考えています)。そのため、メッセージを読む必要があるたびに2つのタスクを作成することにあまり満足していません。

今のところ、私のソリューションは機能しているようですが、一部のマシンでは実行速度が遅いと報告されています。しかし、私のマシンでは非常に高速に実行されているため、コードの問題によるものなのか、それとも他の問題によるものなのかわかりません。

私はそれを正しくやっていますか?このソリューションを改善する方法はありますか?

編集:Jeroen Mostertとusrからの提案に基づいて、次のようにコードを更新しました。

public async Task<Message> GetMessageAsync(CancellationToken token)
{
    using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token, new CancellationToken(false)))           
    {
        var taskList = new List<Task<Message>> {
            GetDevice1Async(cts.Token),
            GetDevice2Async(cts.Token)
        };

        // wait for any operation to finish, then cancel the other one
        var task = await Task.WhenAny(taskList);
        cts.Cancel();

        //ensure both operations are either finished or cancelled before returning
        try {
            await Task.WhenAll(taskList);
        }
        catch (OperationCanceledException)
        { 
            //The exception is expected as is safe to ignore
        }

        return task.Result;
    }            
}
usr

基本的に、これは問題ありません。

ただし、問題の1つは、常に1つのタスクを放棄していることです。キャンセルを要求されますが、キャンセルしない場合は引き続き実行されます。これはリソース使用量を蓄積する可能性があり、あなたが見ている遅さを説明するかもしれません。

.NETでは、IOが簡単にキャンセルできることはめったにありません。たとえば、ソケットの場合、ソケットを閉じる以外にIOをキャンセルすることはできません。USBデバイスと通信するときは、キャンセルが実際に機能することを確認する必要があります。

別の問題はcts、トークンが最後に使用された後に破棄される可能性があることです。呼び出した時点で、トークンに登録さcts.Dispose()れる可能性のあるタスクがまだ1つ実行されています。それが機能することが保証されているかどうかはわかりません。

キャンセルされた操作が実際にキャンセルされるのを待つことで、これを修正できます。

    cts.Cancel();
    await Task.WhenAll(tasks); //Maybe need to swallow exceptions.
    return response.Result;

Task.Run(async通常のメソッド呼び出しだけに単純化できる可能性があります。これにより、セマンティクスが少し変わります。同期コンテキストを通過させ、asyncメソッドの一部を同期的に実行します。あなたはそれを望むかもしれないし、望まないかもしれません。これは重大な効率の問題ではありません。私の主観的な評価は、このTask.Runパターンがコードを明確にし、コードを正しく理解しやすくすることです。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

非同期メソッドが終了するのを待っています

分類Dev

2つの異なる非同期メソッドの結果に基づいて結果を設定する方法

分類Dev

nodejsは、結果を返す前に非同期関数が完了するのを待っていません

分類Dev

webfluxコード内で非同期メソッドの結果を待つ方法があります

分類Dev

非同期/結果を返すのを待つことは約束されていません

分類Dev

非同期操作の結果を待たずに待つにはどうすればよいですか?

分類Dev

別のメソッドが呼び出されるのを待ってから、結果を続行します

分類Dev

非同期メソッドを待っています

分類Dev

メソッドは、非同期が完了するのを待ってから次の行に移動します

分類Dev

2つの非同期メソッドから値を返すにはどうすればよいですか?

分類Dev

多形の結果を持つ非同期タスクのリストを待っています

分類Dev

結果が必要になる前に待機中の非同期メソッドが返されない

分類Dev

最初の呼び出しの結果を待っている非同期メソッドにさまざまな呼び出しを行う方法は?

分類Dev

非同期メソッドの結果が得られるまでプログラムを一時停止するにはどうすればよいですか?

分類Dev

ネットワーク要求が非同期で実行されるのを待って、結果をメインスレッドで処理するにはどうすればよいですか?

分類Dev

Task.WhenAnyを使用していくつかの異なる非同期操作の結果を待ちます

分類Dev

非同期メソッドが完了するのを待つ方法は?

分類Dev

非同期メソッドが終了するのを待つ

分類Dev

非同期メソッドが完了するのを待つ

分類Dev

非同期ラムダ式内のすべての非同期メソッドが終了するのを待つ

分類Dev

結果を待つ非同期と同期の違いは何ですか?

分類Dev

非同期メソッドのタスク結果を実行せずにキューに入れるにはどうすればよいですか?

分類Dev

待機することができ、終了するのを待たずに非同期で実行できる非同期メソッドを宣言しますか?

分類Dev

以前の非同期メソッドのいずれかが実行された後、Javaでメソッドを実行しますか?

分類Dev

現在の関数/スレッドで結果を待たずに非同期タスクを実行するにはどうすればよいですか?

分類Dev

Typescriptで2つのタイプのいずれかを返すメソッド

分類Dev

2つのスレッドが同期メソッドに入るのを待っている場合、ミューテックスが解放されると、到着した順に実行されますか?

分類Dev

いくつかの同期コードを実行する前に、JS非同期関数が完了するのを待っています

分類Dev

非同期で頭を包むのが待っています

Related 関連記事

  1. 1

    非同期メソッドが終了するのを待っています

  2. 2

    2つの異なる非同期メソッドの結果に基づいて結果を設定する方法

  3. 3

    nodejsは、結果を返す前に非同期関数が完了するのを待っていません

  4. 4

    webfluxコード内で非同期メソッドの結果を待つ方法があります

  5. 5

    非同期/結果を返すのを待つことは約束されていません

  6. 6

    非同期操作の結果を待たずに待つにはどうすればよいですか?

  7. 7

    別のメソッドが呼び出されるのを待ってから、結果を続行します

  8. 8

    非同期メソッドを待っています

  9. 9

    メソッドは、非同期が完了するのを待ってから次の行に移動します

  10. 10

    2つの非同期メソッドから値を返すにはどうすればよいですか?

  11. 11

    多形の結果を持つ非同期タスクのリストを待っています

  12. 12

    結果が必要になる前に待機中の非同期メソッドが返されない

  13. 13

    最初の呼び出しの結果を待っている非同期メソッドにさまざまな呼び出しを行う方法は?

  14. 14

    非同期メソッドの結果が得られるまでプログラムを一時停止するにはどうすればよいですか?

  15. 15

    ネットワーク要求が非同期で実行されるのを待って、結果をメインスレッドで処理するにはどうすればよいですか?

  16. 16

    Task.WhenAnyを使用していくつかの異なる非同期操作の結果を待ちます

  17. 17

    非同期メソッドが完了するのを待つ方法は?

  18. 18

    非同期メソッドが終了するのを待つ

  19. 19

    非同期メソッドが完了するのを待つ

  20. 20

    非同期ラムダ式内のすべての非同期メソッドが終了するのを待つ

  21. 21

    結果を待つ非同期と同期の違いは何ですか?

  22. 22

    非同期メソッドのタスク結果を実行せずにキューに入れるにはどうすればよいですか?

  23. 23

    待機することができ、終了するのを待たずに非同期で実行できる非同期メソッドを宣言しますか?

  24. 24

    以前の非同期メソッドのいずれかが実行された後、Javaでメソッドを実行しますか?

  25. 25

    現在の関数/スレッドで結果を待たずに非同期タスクを実行するにはどうすればよいですか?

  26. 26

    Typescriptで2つのタイプのいずれかを返すメソッド

  27. 27

    2つのスレッドが同期メソッドに入るのを待っている場合、ミューテックスが解放されると、到着した順に実行されますか?

  28. 28

    いくつかの同期コードを実行する前に、JS非同期関数が完了するのを待っています

  29. 29

    非同期で頭を包むのが待っています

ホットタグ

アーカイブ