1

RESTful Web サービスをラップするクラス ライブラリ (他の開発者が使用するため) を開発しています。名前空間のHttpClient型を使用して、すべての API 呼び出しを非同期的に実行しています。System.Net.Http

単純にコンテンツを送受信するだけでなく、返された XML データに対して追加の処理を実行したいと考えています。どのように表現しても、これにはクラス ライブラリのどこかで Async/Await キーワードを使用することが含まれます。

私の質問は、Async キーワードを使用するメソッドを公開するのが良い考えか悪い考えか、そしてその理由です。Async メソッドを非公開にしてから、return ステートメントだけで追加のメソッドを作成する必要があることをどこかで読みました。それが私がやってきたことですが、それは正しくないと感じています。

Public Function InvokeAsync(command As HttpRequestMessage) As Task(Of CommandResult)
    Return InvokeAsyncInternal(command)
End Function

Private Async Function InvokeAsyncInternal(command As HttpRequestMessage) As Task(Of CommandResult)
    Dim rawCommandResult As HttpResponseMessage = Await myHttpClient.SendAsync(command)
    Dim finalResult As CommandResult = AdditionalProcessing(rawCommandResult)
    Return finalResult
End Function

これは非常に単純化されたコード サンプルであることを念頭に置いてください。Async メソッドを直接公開しないようにするための適切な議論はありますか?

4

2 に答える 2

4

これは、コンパイラの変換に関係しています。「実際の」Asyncメソッドを対応するメソッドから分離することができ、反復子 ( ) メソッドPublicに対して同じ種類の分離を行う場合と同じ利点が得られます。Yield

特に、ラッパーからスローされた場合とAsyncメソッドからスローされた場合では、例外の処理が異なります。返されるAsyncメソッドが をTaskスローすると、呼び出し元に直接スローされるのではなくException、返される に配置されます。ラッパー メソッド ( ではない) が をスローTaskすると、呼び出し元に直接スローされます。PublicAsyncException

Publicしたがって、前提条件スタイルのチェックをメソッドに入れることができます。呼び出し元はTasks に配置された例外を無視できますが、直接スローされた例外を無視することはできません。前提条件の例外をPublicラッパーに配置すると、呼び出し元は API を誤用していることを認識するようになり、使用例外 (直接スローされる) を実行時例外 (に配置される) から分離することもできますTask

メソッドに前提条件がない場合、Publicラッパーは単に inner を返していTaskます。この場合、Publicラッパーは不要です。

于 2013-01-25T14:39:10.887 に答える
0

次のシナリオを検討してください。

void Caller()
{
    var t = AsyncThatThrows(null);
    // ...
    Task.WaitAny(t, t2); // <-- exception thrown here
}

Task AsyncThatThrows(Object o)
{
    if (o == null)
        throw new ArgumentNullException("o");

    // ...
    await // ...
    // ...
}

例外は最初の await のにスローされますが、タスクの検査時にのみ例外が再スローされることに注意してください。それを待つか、結果を取得するか。次の方法で実装することを選択した場合:

void Caller()
{
    var t = AsyncThatThrows(null);// <-- exception thrown here
    // ...
    Task.WaitAny(t, t2);
}

Task AsyncThatThrows(Object o)
{
    if (o == null)
        throw new ArgumentNullException("o");

    return AsyncThatThrows_Impl(o);
}

Task AsyncThatThrows_Impl(Object o)
{
    // ...
    await // ...
    // ...
}

これで、呼び出し時に例外をキャッチできるようになりました。タスクを検査する必要はありません。前者の場合、まだ非同期部分を開始していなくても、結果の Task に例外が格納されます。

于 2013-01-25T17:10:52.107 に答える