C# で簡単に await/async に置き換える方法
C# には便利な EventHandler
というものがあります。
とある処理が完了した時点で事前に登録されているイベントハンドラーが実行されるものです。
例えば以下のような Process
を await/async に置き換えてみます。
(※Process.WaitForExitAsync
があるやんけとかは言わないでください…)
var startInfo = new ProcessStartInfo {
FileName = "dir",
UseShellExecute = false,
ErrorDialog = false,
};
var process = new Process {
StartInfo = startInfo,
EnableRaisingEvents = true,
};
process.Exited += (sender, args) => {
// プロセス終了
};
これを await
で待機可能にするには…
public static Task<int> RunAsync(this Process process)
{
var exited = new TaskCompletionSource<int>();
process.Exited += (sender, args) => {
exited.TrySetResult(process.ExitCode);
};
if (!process.Start()) {
throw new InvalidOperationException($"Could not start process: {process}");
}
return exited.Task;
}
みたいな拡張機能を作成して…
await process.RunAsync();
で待機することが可能です。
新規で作成するクラスの場合 INotifyCompletion
やらを使用して初めから待機可能にすることも出来ますが、既存クラスを待機可能にするだけであれば上記の例のように TaskCompletionSource
を使えば簡単に待機可能に出来ます。
public static Task<T> ????Async<T>(this ???? awaitable)
{
var tcs = new TaskCompletionSource<T>();
// awaitable の非同期処理終了時に tcs.TrySetResult を呼び出す
return tcs.Task;
}
みたいな感じです。