私は、ジョブを非同期で実行し、進行が行われるたびにイベントを発生させる「バックグラウンドジョブ」クラスを持っています。このイベントのイベントハンドラで例外が発生した場合、呼び出し元のメソッドで捕捉されることはありません。非同期イベントハンドラから例外をキャッチ
イベントハンドラを非同期に切り替えるとどうなりますか。問題は解消されます。しかし、その後、イベントハンドラから非同期呼び出しをすべて呼び出しをブロックするようにしなければならず、そうする必要はありません。
非同期イベントハンドラから発生した例外をキャッチする方法はありますか?
using System;
using System.Threading.Tasks;
namespace AsyncEventHandlingIssue
{
public class BackgroundJob
{
public int Progress { get; private set; }
public event EventHandler ProgressUpdated;
public async Task Start()
{
for (var i = 0; i < 100; i++)
{
await Task.Delay(1000);
Progress++;
ProgressUpdated?.Invoke(this, EventArgs.Empty);
}
}
}
public class Program
{
static async Task MainAsync()
{
var job = new BackgroundJob();
job.ProgressUpdated += Job_ProgressUpdated;
try
{
await job.Start();
}
catch(Exception ex)
{
Console.WriteLine($"The job failed with an error: {ex}");
}
}
private static async void Job_ProgressUpdated(object sender, EventArgs e)
{
var job = (BackgroundJob)sender;
await Task.Delay(100); // just an example - my real code needs to call async methods.
Console.WriteLine($"The Job is at {job.Progress}%.");
if (job.Progress == 5)
throw new Exception("Something went wrong!");
}
static void Main(string[] args)
{
MainAsync().GetAwaiter().GetResult();
Console.WriteLine("Reached the end of the program.");
Console.ReadKey();
}
}
}
あなたは間違った質問をするように導かれました。進捗レポートはObserverパターンの実装です。イベントソースでハンドラ例外を捕まえることは決して必要ありません。あなたがObserverパターンを使用しているのではなく、何か他のものを使用していることを示す必要があるという事実。たとえば、テンプレートメソッドはイベントを使用して誤って実装されることがあります。 –
@StephenClearyそれは非常に良い点です。私は確かにあなたが示唆しているものの有罪と私はかなり私はこの問題を避けるために私はJStewardから得たヒントを使用して書き換えることができると確信しています。さて、それでは、個人的な好奇心のためだけに、イベント処理コードから例外がスローされる可能性はありませんか?そして、非同期voidイベントハンドラからの例外を捕らえることができない場合、アプリケーションをクラッシュさせないために、try/catchのブランケットに常にラップするべきではありませんか?ありがとう! –
'async void'は、(トップレベルの)UIイベントハンドラをエミュレートします。 UIイベントが例外を発生させると、それはメッセージループにまっすぐ進むので、 'async void'メソッドは' SynchronizationContext'で直接例外を発生させることでその動作をエミュレートします。したがって、あなたのUIイベントハンドラでtry/catchが必要な場合は、 'async void'メソッドで必要になります。例外を捕まえることを可能にするいくつかの回避策があります( 'Task'を返すイベントのように)が、再設計が最善のアプローチです。 –