80

通常は非同期に表示されるアラート ウィンドウ (Telerik WPF) を使用しています (コードは開いている間も実行され続けます)。async/await を使用して同期させたいと考えています。

私はこれを使用していますが、そのクラスはジェネリックであり、戻り値のないプレーンだけが必要な場合のTaskCompletionSourceようにオブジェクトを返します。Task<bool>Task

public Task<bool> ShowAlert(object message, string windowTitle)
{
    var dialogParameters = new DialogParameters { Content = message };

    var tcs = new TaskCompletionSource<bool>();
    dialogParameters.Closed += (s, e) => tcs.TrySetResult(true);

    RadWindow.Alert(dialogParameters);

    return tcs.Task;
}

そのメソッドを呼び出すコードは

await MessageBoxService.ShowAlert("The alert text.")

dialogParameters.Closedイベントが発生するまで待機できる、同様に機能する非ジェネリックなタスクを返すにはどうすればよいですか? boolこのコードで返される を無視できることを理解しています。私はそれとは異なる解決策を探しています。

4

5 に答える 5

101

メソッドは次のように変更できます。

public Task ShowAlert(object message, string windowTitle)

Task<bool>から継承するため、呼び出し元に公開するだけでTask戻ることができますTask<bool>Task

編集:

Stephen Toub による「The Task-based Asynchronous pattern」という Microsoft ドキュメントhttp://www.microsoft.com/en-us/download/details.aspx?id=19957を見つけました。これと同じパターン。

TaskCompletionSource<TResult> に対応する非汎用のものはありません。ただし、Task<TResult> は Task から派生するため、汎用の TaskCompletionSource<TResult> は、ダミーの TResult を持つソースを利用することで単に Task を返す I/O バウンド メソッドに使用できます (Boolean は適切な既定の選択であり、開発者が Task の消費者がそれを Task<TResult> にダウンキャストすることを懸念している場合は、プライベート TResult 型を使用できます)。

于 2012-08-15T12:27:42.360 に答える
56

情報を漏らしたくない場合、一般的なアプローチは、 を使用TaskCompletionSource<object>して結果を補完することですnull。次に、それを として返しTaskます。

于 2012-08-15T12:59:17.360 に答える
3

Nito.AsyncExは非ジェネリックTaskCompletionSourceクラスを実装します。上記の @StephenCleary 氏の功績によるものです。

于 2015-07-25T17:28:42.383 に答える
1

@Kevin Kalitowski から

http://www.microsoft.com/en-us/download/details.aspx?id=19957、Stephen Toub による「The Task-based Asynchronous pattern」という Microsoft ドキュメントを見つけました。

このドキュメントには、Kevin が指摘しているように、この問題を扱っていると思われる例があります。これは例です:

public static Task Delay(int millisecondsTimeout)
{
    var tcs = new TaskCompletionSource<bool>();
    new Timer(self =>
    {
        ((IDisposable)self).Dispose();
        tcs.TrySetResult(true);
    }).Change(millisecondsTimeout, -1);
    return tcs.Task;
}

最初は、コンパイル メッセージなしで "async" 修飾子をメソッドに直接追加できないため、これは良くないと思いました。ただし、メソッドを少し変更すると、メソッドは async/await でコンパイルされます。

public async static Task Delay(int millisecondsTimeout)
{
    var tcs = new TaskCompletionSource<bool>();
    new Timer(self =>
    {
        ((IDisposable)self).Dispose();
        tcs.TrySetResult(true);
    }).Change(millisecondsTimeout, -1);
    await tcs.Task;
}

編集:最初は、こぶを乗り越えたと思いました。しかし、自分のアプリで同等のコードを実行すると、このコードは tcs.Task; を待機するときにアプリをハングさせるだけです。したがって、これは async/await c# 構文の重大な設計上の欠陥であると私は今でも信じています。

于 2016-08-22T23:19:23.317 に答える