42

私は、複数のクライアントオブジェクトがインターフェースを介して特定の機能を実装することが期待されているシステムに取り組んでいます。そして、その機能を継続と非同期的に実行することを望みます。すべてのクライアントオブジェクトができるだけ早くこの機能を完了するようにしてください。 C# "5.0"のSP1用のVisual Studio非同期CTP更新を使用しています。

抽象クラスの子オブジェクトで非同期動作を強制するための推奨される方法は何ですか(下記参照)。私は(明らかに)仮想メソッドアプローチを使って '非同期'メソッドの使用を強制することはできません。 'Task'の返品タイプのみが必要です。つまり、子オブジェクトでは非同期動作をまったく要求しないようにする必要がありますか?その場合、戻り型は単に 'void'であるべきですか?

パブリックインタフェースは、今のところシステム設計の不幸な結果ですが、それは別の問題です。明らかに、 'BaseFoo'を迂回し、単に 'IFoo'インターフェースを実装するだけで、誰にも非同期であることを強制することはできませんでした。

これがコードです:

public interface IFoo
{
    void Bar(); //NOTE: Cannot use 'async' on methods without bodies.
}

public abstract class BaseFoo : IFoo
{
    public async void Bar()
    {
        await OnBar(); //QUESTION: What is the right "async delegation" pattern?
    }

    protected virtual async Task OnBar()
    {
        await TaskEx.Yield();
    }
}

public class RealFoo : BaseFoo //NOTE: May be implemented by 3rd party
{
    protected override async Task OnBar()
    {
        //CLIENT: Do work, potentially awaiting async calls

        await TaskEx.Yield(); //SECONDARY QUESTION: Is there a way to avoid this if there are no 'awaits' in the client's work?
    }
}

2 답변


78

メソッドがを使って実装されているかどうかasync/awaitかどうかは実装詳細方法はどうあるべきか振る舞う契約の詳細です。通常の方法で指定する必要があります。

あなたがメソッドを返すようにすると注意してくださいTaskまたはTask<T>それは非同期であることを意図していること、そしておそらく実装するのが難しいだろうことはより明白ですなしで非同期です。

一方、(テスト目的などの)実装がある場合は、await式は決して不完全である、なぜあなたは誰かにnoで非同期メソッドを書くことを強制したいと思うでしょうawaitとにかく電話?あなたは期待して実装はIOバウンドであるべきですが、実装がハードコードされたデータなどを使いたいという特別な場合があるでしょう。

基本的にはメソッドのドキュメントでこれを処理する必要があります - 実装者がそれを読むことを信頼できないのであれば、とにかくチャンスはありません:(


  • どうもありがとうございました。実装と動作の区別は非常に役立ちます。私は西暦前にそれを聞いたことがなかった。非同期待ち。私は、Bar契約を無効のままにすることを選択しました。 IFooとBaseFooの両方で、RealFooに非同期性を判断させるためです。これにより、RealFoo.Barの戻り値も単純化されます。 - Lars Kemmann
  • @ラース:私は使用したくなるでしょうTask戻り型ではなくvoidいつでもどこでも - void非同期メソッドを使ってイベントハンドラを実装できるようにするためです。非同期メソッドが完了するのを待つことができると便利なことがよくあります。Taskそれは簡単です。 - Jon Skeet
  • さて、それは理にかなっています。もう少しタスクを返すことの意味を調べます。再度、感謝します! - Lars Kemmann

16

Jonの答えに加えて、あなたがフォローしているならタスクベースの非同期パターンそれからあなたのメソッド名は接尾辞を付けるべきですAsyncこれは、それが非同期メソッドであることを自己証明しています。

あなたがインターフェースを実装しているなら

public interface IFoo
{
    Task BarAsync();
}

これがで実装されるべきであることは明らかであるべきですasyncキーワード。

リンクされた質問


関連する質問

最近の質問