C#:非同期なイベント?

執筆日時:

たとえばこんなコードがあるとする。ラムダ式でイベントハンドラを実装する、よくあるヤツ。

public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += (sender, reason) => { Hoge(); };
}

イベントハンドラ内で非同期コードがある場合は、こんな感じになる。

public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += async (sender, reason) =>
{
await Hoge();
};
}

async/await を付け足すだけなので、そんなに難しくはない。

次に、イベントハンドラのコードが肥大化してきたので、これを外に出すことにする。

非同期じゃない場合はこんな感じ。

public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += taskInstanceCanceled;
}

private void taskInstanceCanceled( IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) { Hoge(); : : }

これをさっきみたいに非同期にすると、

public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += taskInstanceCanceled;
// taskInstance.Canceled += async taskInstanceCanceled;
}

private async Task taskInstanceCanceled(
IBackgroundTaskInstance sender,
BackgroundTaskCancellationReason reason)
{
await Hoge();
:
:
}

になると思うんだけど、

taskInstance.Canceled += taskInstanceCanceled;

ここでエラーになる(taskInstanceCanceled の返り値が void ではなく Task なので)。

しょうがないので、ちょっと考えてこうした。

public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += async (sender, reason) =>
{
await taskInstanceCanceled(sender, reason);
};
}

private async Task taskInstanceCanceled(
IBackgroundTaskInstance sender,
BackgroundTaskCancellationReason reason)
{
await Hoge();
:
:
}

動いたっぽいんだけどなんかしっくりこないので、今度詳しい人に聞いてみたい。