运行以下代码:
using static System.Console;
WriteLine("Handling cancellations and exceptions.");
CancellationTokenSource cts = new();
CancellationToken token = cts.Token;
var transferMoney = Task<string>.Factory.StartNew(
() =>
{
WriteLine($"Initiating the money transfer.");
int progressBar = 0;
WriteLine("Press c to cancel withing 5 sec.");
// Assuming the task will take 5 seconds.
// So, after every second, we'll increase the progress by 20%
for (int i = 0; i < 5; i++)
{
token.ThrowIfCancellationRequested();
Thread.Sleep(1000);
progressBar += 20;
WriteLine($"Progress:{progressBar}%");
}
return "Money transfer is completed.";
}, token);
var input = ReadKey().KeyChar;
if (input.Equals('c'))
{
WriteLine("\nCancellation is requested.");
cts.Cancel();
}
try
{
transferMoney.Wait();
WriteLine(transferMoney.Result);
}
catch (AggregateException ae)
{
ae.Handle(e =>
{
WriteLine($"Caught error : {e.Message}");
return true;
});
}
catch (OperationCanceledException oce)
{
WriteLine($"Caught error due to cancellation :{oce.Message}");
}
WriteLine($"Payment processing status: {transferMoney.Status}");
WriteLine("Thank you, visit again!");
以下是示例输出(预期行为--毫无疑问):
Handling cancellations and exceptions.
Initiating the money transfer.
Press c to cancel withing 5 sec.
Progress:20%
Progress:40%
Progress:60%
c
Cancellation is requested.
Progress:80%
Caught error : A task was canceled.
Payment processing status: Canceled
Thank you, visit again!
现在使用以下语句之一更新Try块:
try
{
//transferMoney.Wait();
transferMoney.Wait(token);
//await transferMoney; //Same observation
// There is no change in the remaining code
然后再次运行代码.以下是一个样例输出.
Handling cancellations and exceptions.
Initiating the money transfer.
Press c to cancel withing 5 sec.
Progress:20%
Progress:40%
c
Cancellation is requested.
**Caught error due to cancellation :The operation was canceled.**
Payment processing status: Running
Thank you, visit again!
请注意,这一次AggregateException的Catch块不足以处理OperationCanceledException.我想知道这背后的原因.你能分享你的 idea 吗--我错过了哪里? [补充说明:我知道在前面的例子中,Wait()只能抛出AggregateException,但这个重载版本的Wait(即Wait(Token))也会抛出OperationCancelledException.]