`に依存:例外動作は、私は次のシナリオを有するasync`キーワード
成分Aは、インタフェースIMyInterface
とその実装を登録する他の成分のための登録メカニズムを提供します。私は「並列に」のすべての実装のための方法を上開始したいコンポーネントAでは
public interface IMyInterface
{
Task DoSomethingAsync(Context context);
}
して、タスクを待つ:
インタフェースは次のようになります。 実装者は実装に例外をスローすることがあります(具体的なシナリオではIOが関与し、IOExceptionが発生することが予想され、コンポーネントAは例外を正しくキャッチします)。
コードはだからここに、以下の
var tasks = new List<Task>();
foreach (var impl in implementors)
{
var context = ...;
tasks.Add(impl.DoSomethingAsync(context));
}
// now do something different that takes some time
try
{
await Task.WhenAll(tasks);
}
catch(Exception e)
{
// swallow. we handle the exceptions for each task below.
}
foreach (var task in tasks)
{
if (task.IsFaulted)
// log, recover, etc...
}
のように見える私の問題である: 私は、単一のタスクのためのawait
を使用してないておりますので、例外動作が実装者は、「作成」の方法に依存返されたTask
。
public class Implementor1 : IMyInterface
{
public async Task DoSomethingAsync(Context context)
{
// no awaits used in code here!
throw new Exception("oh the humanity");
}
}
public class Implementor2 : IMyInterface
{
public Task DoSomethingAsync(Context context)
{
throw new Exception("oh the humanity");
return Task.CompletedTask;
}
}
(違いに注意してください。最初の実装は、async
キーワードを使用)
インプリ1にDoSomethingAsync
を呼び出す場合、例外がタスク・オブジェクトが「故障」に設定されている成分Aでスローされていないとタスクから例外を取得できます。 - >私が期待した通り。
実装者2でDoSomethingAsync
を呼び出すと、すぐに例外がスローされます。 - >ではない私が欲しいもの。
ここに質問があります: どのようにしてこのような状況で常に行動1を観察できますか?私は、他のコンポーネントの作者が私のインターフェースをどのように実装するかを制御することはできません。
賢いアイデア、私はこの1つが好きです! 私はちょうど1つの行にこれを分解しました: 'tasks.Add(Task.Run(async()=> await impl.DoSomethingAsync(context))); ' –
@ cpt.jazz:私はないと思います'Task.Run'はここでは適切です。実行コンテキストをスレッドプールに変更して、不必要なプレッシャーをかけています。 –
@Stephen:別の方法を避けたいときは、どうすればこれを改善できますか? –