// TaskCreationOptionsと併用するときの注意
// タスクにCancellationTokenだけでなく、TaskCreationOptionsも設定したい場合は
// ちょっとした注意が必要です。
// と言っても、大したことではないです。TaskFactoryのStartNewメソッドに
// CancellationTokenとTaskCreationOptionsを同時に受け付けるオーバーロードがないだけです。
// Taskのコンストラクタにはあるのに何でないんだ、って感じですが、もしStartNewを
// 使いたい場合はこのオーバーロードを使いましょう。
// StartNewメソッドはやたらとオーバーロードが多い上に第二引数にobjectを
// 受け取っちゃうオーバーロードが多数存在するので、引数の順番を間違えてハマらないようにしましょう。
Task.Factory.StartNew(() =>
{
// TODO:非同期処理
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
// それすら面倒だと思ったらCancellationTokenSource.Cancel(Boolean)の方を使いましょう。
// タスクを即時終了する
private CancellationTokenSource _tokenSource = null;
private void btnStart_Click(object sender, EventArgs e)
{
if(_tokenSource == null) _tokenSource = new CancellationTokenSource();
var token = _tokenSource.Token;
Task.Factory.StartNew(() =>
{
// TODO:非同期処理
}, token).ContinueWith(t =>
{
// TODO:あとしまつ
_tokenSource.Dispose();
_tokenSource = null;
if (t.IsCanceled)
{
// TODO:キャンセルされたときの処理
}
});
}
private void btnStop_Click(object sender, EventArgs e)
{
// 即例外を投げてキャンセルさせる
if(_tokenSource != null) _tokenSource.Cancel(true);
}
// これだと面倒なので、
// キャンセル処理をContinueWithでまとめてやりたい場合は、
// CancellationToken.ThrowIfCancellationRequestedメソッドを使うと楽です。
Task.Factory.StartNew(() =>
{
// TODO:非同期処理
// キャンセル通知が来てたら例外を投げてタスクを終了させる
token.ThrowIfCancellationRequested();
// TODO:続きの処理
token.ThrowIfCancellationRequested();
}, token).ContinueWith(t =>
{
// TODO:あとしまつ
_tokenSource.Dispose();
_tokenSource = null;
if (t.IsCanceled)
{
// TODO:キャンセルされたときの処理
}
});
// CancellationTokenSource.Cancelメソッドを使うとCancellationTokenに通知が飛びます。
// 飛んでいったからといって、何がどうなるわけでもないです。非同期処理中に何度か
// IsCancellationRequestedプロパティを見てやる必要があります。
Task.Factory.StartNew(() =>
{
// TODO:非同期処理
if (token.IsCancellationRequested)
{
// TODO:キャンセル処理
return;
}
// TODO:続きの処理
if (token.IsCancellationRequested)
{
// TODO:キャンセル処理
return;
}
}, token).ContinueWith(t =>
{
// TODO:あとしまつ
_tokenSource.Dispose();
_tokenSource = null;
});
private CancellationTokenSource _tokenSource = null;
private void btnStart_Click(object sender, EventArgs e)
{
if(_tokenSource == null) _tokenSource = new CancellationTokenSource();
var token = _tokenSource.Token;
Task.Factory.StartNew(() =>
{
// TODO:非同期処理
}, token).ContinueWith(t =>
{
// TODO:あとしまつ
_tokenSource.Dispose();
_tokenSource = null;
});
}
private void btnStop_Click(object sender, EventArgs e)
{
if(_tokenSource != null) _tokenSource.Cancel();
}