You would normally just use Task.Wait
(instead of WaitAll
), as it's a single task. and then handled the exception appropriately:
private void stopButton_Click(object sender, EventArgs e)
{
cts.Cancel();
try
{
t.Wait(); // This will throw
}
catch (AggregateException ae)
{
ae.Handle<OperationCanceledException>(ce => true);
}
statusTextBox.Text = "Output ended.";
}
When you cancel a Task
, the OperationCanceledException
will get wrapped into an AggregateException
and be thrown as soon as you call Wait()
or try to get the Task's Result
(if it's a Task<T>
).
Purely for your information - This is one place, especially given what you're doing here, where C# 5 simplifies things. Using the new async support, you can write this as:
// No need for "t" variable anymore
// private Task t;
private async void startButton_Click(object sender, EventArgs e)
{
statusTextBox.Text = "Output started.";
// Create the cancellation token source.
cts = new CancellationTokenSource();
try
{
// Create & start worker task.
await Task.Run(() => DoWork(cts.Token));
statusTextBox.Text = "Output ended.";
}
catch(OperationCanceledException ce)
{
// Note that we get "normal" exception handling
statusTextBox.Text = "Operation canceled.";
}
}
private void stopButton_Click(object sender, EventArgs e)
{
// Just cancel the source - nothing else required here
cts.Cancel();
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…