開始後に頻繁にキャンセルする必要がある短い非同期タスクがあります。「タスク」クラスには IsCanceled インジケーターがあり、非同期タスクが実行を完了せずにキャンセルされたことを示すのに便利だと思いますが、非同期タスクをキャンセル済みとしてマークする唯一の方法は非同期関数で TaskCanceledException をスローします。例外なく発生する状況を示すために、日常的に例外をスローすることは、例外を使用する必要があると私が理解している方法に反します。非同期タスクが頻繁に発生すると予想される場合に、非同期タスクをキャンセルすることを示すより良い方法を知っている人はいますか?
私の次善の策は、独自の IsCanceled プロパティを持つ構造体を返すことです。
(ここでは簡潔にするために、いくつかの優れたコーディングとスタイルの実践を無視しています)
class MightBeCanceled<T>
{
public readonly T Value;
public readonly bool IsCanceled;
public MightBeCanceled(T value) { Value = value; IsCanceled = false; }
public static MightBeCanceled<T> Canceled = new MightBeCanceled<T>(default(T), true);
private MightBeCanceled(T value, bool isCanceled) { Value = value; IsCanceled = isCanceled; }
}
...
static async Task<MightBeCanceled<int>> Foo()
{
if (someCancellationCondition)
return MightBeCanceled<int>.Canceled;
else
return new MightBeCanceled<int>(42);
}
static async void Bar()
{
var mightBeCanceled = await Foo();
if (mightBeCanceled.IsCanceled)
; // Take canceled action
else
; // Take normal action
}
しかし、これは冗長で使いにくいようです。IsCanceled が 2 つ (Task に 1 つ、MightBeCanceled に 1 つ) あるため、一貫性の問題が発生することは言うまでもありません。