2

例として LoadState メソッドを使用していますが、これは一般的な非同期プログラミングのシナリオと見なすことができます。

LoadStateandメソッドのSaveState実装には通常、次のシグネチャがあります。

public override void LoadState(..)
public async override void LoadState(..)

一部のデータの読み込みを待機するかどうかに応じて、async キーワードを追加することを選択できます。しかし、戻り値の型がLoadStateisvoidであるため、LoadState メソッド自体は待機できず、fire and forget としてトリガーされます。これは、データ読み込みロジックで async/await を使用できる一方で、レスポンシブ UI を可能にするため、通常は適切です。

いくつかのシナリオでは、async LoadState メソッドを待ちたいと思います。ただし、署名をTaskvoid の代わりに変更すると、非同期ロジックを使用しないすべての実装で null を返す必要があります (これは最善の解決策とは思えません)。一部のメソッド呼び出しを待機し、ほとんどのメソッド呼び出しを待機して忘れる (デフォルトとして) 別の解決策はありますか?

4

4 に答える 4

4

async voidメソッドにはいくつかの問題があります。

  • 構成可能ではありません。完了することはできませんawait(ご指摘のとおり)。
  • 簡単にテストできません(同じ理由で)。
  • エラー処理はまったく異なります。「ファイア アンド フォーゲット」という言葉を聞いたことがasync voidありますが、私は「ファイア アンド クラッシュ」という用語を使用しました。

nullまた、メソッドから戻るべきではありませんAsyncこれは、 TAPに慣れている他のコーダーにとって驚くべきことです。

と の2 つのメソッドvoid LoadStateを提供できTask LoadStateAsyncますが、これを行う場合は、常に両方の実装を提供することをお勧めします。非同期メソッドを同期メソッドにラップしたり、同期メソッドを非同期メソッドにラップしたりする簡単な方法はありません。そのため、実際には 2 つのほぼ同一の実装になってしまいます。

メンテナンス上の理由から、これは特に好きではありません。個人的には、possible-asyncメソッドには常にawait-compatible シグネチャを持たせることを好みます。

interface IWhatever
{
  Task LoadStateAsync();
}

実装は、同期の場合は非同期または高速にする必要があります。同期実装では以下を利用できますTask.FromResult

class Whatever : IWhatever
{
  public Task LoadStateAsync()
  {
    ... // fast-running synchronous code
    return Task.FromResult<object>(null);
  }
}

消費コードは常に次のようになりますasync

Whatever whatever = ...;
await whatever.LoadStateAsync();

実装が同期の場合、消費するコードは呼び出し元に渡らないことに注意してください。を通じて同期的に実行され続けますawait

于 2013-01-07T01:38:19.157 に答える
0

私が見る1つの可能な解決策は、基本クラスで2つのメソッドを定義することです(および追加のロジック用に追加の3つ目):

virtual void LoadState(){}
virtual async Task LoadStateAsync{ }

virtual void SomeOtherLogic(){}

LoadState を呼び出す場所には、2 つのメソッド呼び出しがあります。

LoadState();
await LoadStateAsync();

SomeOtherLogic();

このソリューションでは、SomeOtherLogic が空であるか、LoadState メソッドからのデータを必要としない場合に、LoadState メソッドをオーバーライドできます。データが必要な場合は、LoadStateAsync メソッドを待ってから SomeOtherLogic を実行します。

欠点は、あなた (および他の開発者) が、どのメソッドを使用するか、または使用する必要があるかに常に注意を払う必要があることです。

于 2013-01-06T17:12:50.847 に答える
0

ロードが完了すると発生する Loaded イベントがあると思います。おそらく、Loaded イベントのイベント ハンドラーで続行したいことは何でもできるでしょうか?

于 2013-01-06T16:38:04.910 に答える
0

ロジックをTask-returning メソッドとして実装LoadStateし、戻り値を破棄するだけです。

public override void LoadState() { LoadStateInner(); }
Task LoadStateInner() { await ...; }

これで、継承コントラクトを同時に実行しながら、両方のバリアントを呼び出すことができます。

于 2013-01-06T16:38:28.590 に答える