56

私は、複数のクライアント オブジェクトがインターフェイスを介して特定の関数を実装することが期待されるシステムに取り組んでおり、その関数を継続で非同期に実行したいと考えています (実装が I/O バウンドであることを期待しており、すべてのクライアント オブジェクトができるだけ早くこの機能を完了するようにします)。C# "5.0" を使用して、SP1 用の Visual Studio Async CTP Refresh を使用しています。

抽象クラスの子オブジェクトで非同期動作を強制するための推奨される方法は何ですか (以下を参照)? 仮想メソッド アプローチを使用して「非同期」メソッドの使用を (明らかに) 強制することはできません。「タスク」の戻り型のみを要求できます。これは、子オブジェクトで非同期動作を要求するべきではないということですか? その場合、戻り値の型は単純に「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?
    }
}
4

2 に答える 2

96

メソッドがasync/を使用して実装されるかどうかawaitは、実装の詳細です。メソッドの動作はコントラクトの詳細であり、通常の方法で指定する必要があります。

Taskメソッドにaまたはaを返すようにするTask<T>と、非同期であることがより明確になり、非同期でないと実装が困難になる可能性があることに注意してください。

一方、await式が不完全になることawaitのない実装(テスト目的など)がある場合、とにかく呼び出しなしで非同期メソッドを作成するように強制したいのはなぜですか?実装はIOバウンドであると期待していますが、実装がハードコードされたデータなどを使用したいという特殊なケースがあるかもしれません。

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

于 2011-06-08T05:34:05.047 に答える
21

ジョンの答えに加えて、タスクベースの非同期パターンに従っている場合、メソッド名の末尾に を付ける必要がありますAsync。これは、それが非同期メソッドであることを自己文書化したものです。

インターフェイスを実装している場合

public interface IFoo
{
    Task BarAsync();
}

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

于 2014-10-23T11:29:15.973 に答える