这个问题已经被问到了,但我还是不明白...我试图取消一个任务,但是当我包含ThrowIfCancellationRequested()时,它不会被捕获,如果我不包含它, GUI冻结...
这是我的代码,没有ThrowIfCancellationRequested()运行但冻结了GUI:
public void StartProcess(double myvariable)
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
processThread = Task.Factory.StartNew(() =>
{
while (true)
{
//Do some work with myvariable
if (token.IsCancellationRequested)
{
break;
}
}
}, token);
}
并且未捕获到带有ThrowIfCancellationRequested()的代码,调试器将在行令牌上停止。ThrowIfCancellationRequested():
public void StartProcess(double myvariable)
{
tokenSource = new CancellationTokenSource();
CancellationToken tokenDispatcher = tokenSource.Token;
processThread = Task.Factory.StartNew(() =>
{
try
{
while (true)
{
//Do some work with myvariable
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
break;
}
}
}
catch (AggregateException ae)
{
if (ae.InnerException is OperationCanceledException)
{
Console.WriteLine("Process Thread Cancelled");
}
else
{
Console.WriteLine("ERROR");
}
}
}, token);
}
我在做什么错了?
答案 0 :(得分:1)
ThrowIfCancellationRequested
是取消任务的正确方法。您需要了解的是,取消任务时不会有例外。仅任务的Status
将被设置为Canceled
。您在任务中拥有的try catch块将无济于事。
要获取异常,您需要以异步方法等待Task或使用Wait方法等待任务完成。不建议使用Wait方法,因为您将阻塞当前线程,直到任务完成。
以下是您如何从代码中实现此建议。
public static Task StartProcess(double myvariable)
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
return Task.Factory.StartNew(() =>
{
while (true)
{
//Do some work with myvariable
token.ThrowIfCancellationRequested();
}
}, token);
}
public async Task ExecuteProcess(double myvariable)
{
try
{
await StartProcess(myvariable);
}
catch (OperationCanceledException ex)
{
Console.WriteLine("Process Thread Canceled");
}
catch (Exception ex)
{
Console.WriteLine("ERROR");
}
}
ExecuteProcess方法演示了如何调用函数以获取异常。这样,如果您从UI线程调用方法,也可以防止GUI阻塞。
我建议您阅读documentation on asynchronous programming,以进一步了解其工作原理。