15

void MyMethod(object argument)同じメソッドの同期バージョンと非同期バージョンを持つクラスを作成しています Task MyMethodAsync(object argument)。同期バージョンでは、単純なチェックで引数を検証します

if (argument == null)
    throw new ArgumentNullException("argument");

非同期メソッドでは同じチェックがどのように見えるべきですか?

1) 同期方法と同じ

2)(最初の回答後に更新)

if (argument == null)
    return new Task.Factory.StartNew(() => { throw new ArgumentNullException("argument"); });
4

4 に答える 4

13

それは、いつエラーを発生させたいかによって少し異なります-つまり、熱心に、または awaitable の一部として。イテレータ ブロックと同様に、熱心なエラー チェックが必要な場合は、次のような 2 つのメソッドが必要です。

public Task<int> SomeMethod(..args..) {
    if(..args fail..) throw new InvalidOperationException(...);
    return SomeMethodImpl(...args...);
}
private async Task<int> SomeMethodImpl(...args...)
{
    ... await etc ...
}

これにより、awaitable ではなく、最初の呼び出しの一部として引数チェックが実行されます。例外を awaitable の一部にしたい場合は、それをスローできます。

public async Task<int> SomeMethod(..args..) {
    if(..args fail..) throw new InvalidOperationException(...);
    ... await etc ...
}

ただし、あなたの例では、これが実際にはメソッドではなく、非同期(しかしではない)メソッドであることreturnを示唆しています。あなたはただすることはできません:Taskasyncasync

return new Task(() => { throw new ArgumentNullException("argument"); });

それTaskは決して開始されることはありません-そして決して開始されることはないからです。のようなことをする必要があると思います:

try {
    throw new InvalidArgumentException(...); // need to throw to get stacktrace
} catch(Exception ex) {
    var source = new TaskCompletionSource<int>();
    source.SetException(ex);
    return source.Task;
}

これは... 少し一口で、おそらくもう少しうまくカプセル化できます。Taskこれは、状態にあることを示すa を返しFaultedます。

于 2013-09-06T11:22:34.887 に答える
3

sync メソッドで行ったようにスローするだけです。TPL には、例外を再スローするためのさまざまなメカニズムがあります。たとえば、. Resultプロパティまたはアクセス。Exception財産。

于 2013-09-06T11:23:29.803 に答える