次の方法で共有


SyncAsyncEventHandler<T> 代理人

定義

イベントを処理し、同期的または非同期的に実行できるメソッドを表します。

public delegate System.Threading.Tasks.Task SyncAsyncEventHandler<T>(T e) where T : SyncAsyncEventArgs;
type SyncAsyncEventHandler<'T (requires 'T :> SyncAsyncEventArgs)> = delegate of 'T -> Task
Public Delegate Function SyncAsyncEventHandler(Of T)(e As T) As Task 

型パラメーター

T

に等しいか、または を派生させるイベント引数の SyncAsyncEventArgs型。

パラメーター

e
T

SyncAsyncEventArgsイベント データを格納しているインスタンス。

戻り値

ハンドラーを表すタスク。 同期ハンドラーを実装する場合は、 を返 CompletedTask すことができます。 詳細については、「解説」セクションを参照してください。

クライアントの同期ブロック メソッド (非同期サフィックスのないメソッド) を使用している場合は、ハンドラーも同期的に実行する必要があるイベントが発生します。 ハンドラーのシグネチャから が返 Taskされる場合でも、完了したらブロックして返 CompletedTask す通常の同期コードを記述する必要があります。

var client = new AlarmClient();
client.Ring += (SyncAsyncEventArgs e) =>
{
    Console.WriteLine("Wake up!");
    return Task.CompletedTask;
};

client.Snooze();
   If you need to call an async method from a synchronous event handler,
   you have two options.  You can use <xref data-throw-if-not-resolved="true" uid="System.Threading.Tasks.Task.Run(System.Action)"></xref> to
   queue a task for execution on the ThreadPool without waiting on it to
   complete.  This "fire and forget" approach may not run before your
   handler finishes executing.  Be sure to understand
処理されない例外によってプロセスが破棄されるのを防ぐために、タスク並列ライブラリの例外処理。 ハンドラーから戻る前に非同期メソッドを実行する必要がある場合は、 を呼び出 myAsyncTask.GetAwaiter().GetResult()すことができます。 ThreadPool が枯渇する可能性があることに注意してください。 詳細については、「解説」の sync-over-async に関するメモを参照してください。

クライアントの非同期の非ブロッキング メソッド (つまり、Async サフィックスを持つメソッド) を使用している場合は、ハンドラーが非同期的に実行されることを期待するイベントが発生します。

var client = new AlarmClient();
client.Ring += async (SyncAsyncEventArgs e) =>
{
    await Console.Out.WriteLineAsync("Wake up!");
};

await client.SnoozeAsync();

クライアントで同期メソッドと非同期メソッドのどちらを呼び出しているかに応じて、同期コード パスと非同期コード パスの両方から同じイベントを発生させることができます。 非同期ハンドラーを記述し、同期メソッドから発生させる場合、ハンドラーは sync-over-async を実行し、ThreadPool の枯渇を引き起こす可能性があります。 詳細については、「解説」のメモを参照してください。 イベントの発生方法をIsRunningSynchronouslyチェックし、それに応じてハンドラーを実装するには、 プロパティを使用する必要があります。 同期と非同期の両方のコード パスから呼び出しても安全なハンドラーの例を次に示します。

var client = new AlarmClient();
client.Ring += async (SyncAsyncEventArgs e) =>
{
    if (e.IsRunningSynchronously)
    {
        Console.WriteLine("Wake up!");
    }
    else
    {
        await Console.Out.WriteLineAsync("Wake up!");
    }
};

client.Snooze(); // sync call that blocks
await client.SnoozeAsync(); // async call that doesn't block

注釈

.NET 用のほとんどの Azure クライアント ライブラリでは、Azure サービスを呼び出すための同期メソッドと非同期メソッドの両方が提供されています。 非同期メソッドは、非同期サフィックスで区別できます。 たとえば、BlobClient.Download と BlobClient.DownloadAsync は同じ基になる REST 呼び出しを行い、ブロックするかどうかのみが異なります。 新しいアプリケーションには非同期メソッドを使用することをお勧めしますが、同期メソッドを使用する場合も完全に有効なケースがあります。 これらのデュアル メソッド呼び出しセマンティクスでは柔軟性が確保されますが、イベント ハンドラーを記述するときは少し注意が必要です。

SyncAsyncEventHandler は、同期または非同期コード パスから呼び出すことができるイベント ハンドラーを表すために、Azure クライアント ライブラリのイベントによって使用されるデリゲートです。 イベント ハンドラーを記述するための重要な情報を含む から SyncAsyncEventArgs 派生したイベント引数を受け取ります。

  • CancellationToken は、イベントを発生させた元の操作に関連するキャンセル トークンです。 ハンドラーでは、トークンを受け取る非同期または実行時間の長い同期操作にこのトークンを渡すことが重要です。そのため、キャンセル (など new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token) が正しく伝達されます。
  • IsRunningSynchronously は、ハンドラーが同期的に呼び出されたか非同期的に呼び出されたかを示すフラグです。 クライアントで同期メソッドを呼び出す場合は、同期メソッドを使用してイベント ハンドラーを実装する必要があります (を返 CompletedTaskすことができます)。 クライアントで非同期メソッドを呼び出す場合は、可能な限り非同期メソッドを使用してイベント ハンドラーを実装する必要があります。 クライアントの使用方法を制御できない場合、またはより安全なコードを記述する場合は、 プロパティをチェックIsRunningSynchronouslyし、指示に応じて sync メソッドまたは async メソッドを呼び出す必要があります。
  • ほとんどのイベントは、 から SyncAsyncEventArgs 派生し、イベントのトリガーに関する詳細を含めたり、対応するオプションを提供したりして、イベント データをカスタマイズします。 多くの場合、追加の処理に必要な場合に備えて、イベントを発生させたクライアントへの参照が含まれます。

SyncAsyncEventHandler を使用するイベントが発生すると、意図しない並列処理が発生しないようにハンドラーが順番に実行されます。 イベント ハンドラーは、イベントを発生させるコード パスに制御を返す前に終了します。 これは、同期的に発生したイベントをブロックし、返された が非同期的に発生した Task イベントの完了を待機することを意味します。

ハンドラーからスローされた例外は、1 つの AggregateExceptionにラップされます。 1 つのハンドラーが例外をスローした場合、他のハンドラーの実行は妨げません。 これは、取り消しが発生した場合でもすべてのハンドラーが発生するため、取り消しにも関連します。 非同期または実行時間の長い同期操作に渡し CancellationToken 、コンピューティング負荷の高いハンドラーでの 呼び出し ThrowIfCancellationRequested() を検討する必要があります。

分散トレーススパンは、イベント名を使用してハンドラーの周りにラップされるため、ハンドラーの実行にかかった時間、Azure サービスへの他の呼び出しを行ったかどうか、スローされた例外の詳細を確認できます。

同期コード パスからの非同期コードの実行は、同期動作を取得しているが、すべての非同期機構を呼び出しているため、一般に sync-over-async と呼ばれます。 パフォーマンスの重大な問題の原因の詳細については、「 PerfView を使用した Core ThreadPool Starvation の Diagnosing.NET」を参照してください。 ThreadPool の枯渇を回避するには、 IsRunningSynchronously フラグを使用することをお勧めします。

適用対象