Bla*_*lau 4 c# task-parallel-library
我昨天刚刚介绍了Tasks(TPL),所以我尝试做一些示例项目,以便了解如何使用它们.
我的示例项目设置了一个开始按钮,开始递增进度条.第二个按钮取消任务.一个文本框用于报告何时调用使用TaskContinuationOptions.OnlyOnRanToCompletion的延续,以及一个文本框,用于报告何时调用使用TaskContinuationOptions.OnlyOnCanceled的继续.
我可以创建并执行一个Task,但是以一种让TaskContinuationOptions.OnlyOnCanceled标志继续触发的方式取消它是一个问题.
我创建如下任务:
private void StartTask()
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Task task = null;
task = Task.Factory.StartNew(() => DoWork(tokenSource), tokenSource.Token);
//A list<CancellationTokenSource> so that I can cancel the task when clicking a button on the UI Thread.
MyTasks.Add(tokenSource);
Task completed = task.ContinueWith(result => TaskCompleted(), TaskContinuationOptions.OnlyOnRanToCompletion);
Task canceled = task.ContinueWith(result => TaskCanceled(), TaskContinuationOptions.OnlyOnCanceled);
}
Run Code Online (Sandbox Code Playgroud)
我取消了以下任务:
private void CancelTasks()
{
foreach (CancellationTokenSource tokenSource in MyTasks)
{
tokenSource.Cancel();
}
}
Run Code Online (Sandbox Code Playgroud)
我的工作人员功能如下:
private void DoWork(CancellationTokenSource tokenSource)
{
if (progressBar1.InvokeRequired)
{
progressBar1.Invoke(new Action(() => DoWork(tokenSource)));
return;
}
try
{
bool dowork = true;
while (dowork)
{
tokenSource.Token.ThrowIfCancellationRequested();
if (progressBar1.Value == progressBar1.Maximum)
{
dowork = false;
}
Thread.Sleep(1000);
progressBar1.PerformStep();
Application.DoEvents();
}
countCompleted++;
}
catch (OperationCanceledException)
{
}
}
Run Code Online (Sandbox Code Playgroud)
在我读过的其他帖子中,有人建议使用tokenSource.Token.ThrowIfCancellationRequested()来设置TaskContinuationOptions.OnlyOnCanceled评估的条件.
我见过的所有例子都没有包括使用:
catch (OperationCanceledException)
{
}
Run Code Online (Sandbox Code Playgroud)
但是,如果没有它,程序会在我调用tokenSource.Cancel()时停止;
就目前而言,当我调用tokenSource.Cancel()时,运行TaskContinuationOptions.OnlyOnRanToCompletion的Continuation,而不是TaskContinuationOptions.OnlyOnCanceled.
显然,我没有正确地做到这一点.
编辑:
进一步阅读,我发现一条评论说:
"catch(OperationCanceledException){}会将任务的状态设置为RanToCompletion,而不是"已取消"
因此,删除catch(OperationCanceledException){}允许将任务的状态设置为取消,但程序在tokenSource.Token.ThrowIfCancellationRequested(); 但如果我继续休息,那么TaskContinuationOptions.OnlyOnCanceled的延续任务就会运行,这很好.
但是如何调用tokenSource.Token.ThrowIfCancellationRequested()而不允许程序中断并允许将任务状态设置为Canceled?
Moo*_*ght 10
上述注释在调试器和防止调试器中断所需的选项方面是正确的.但是,以下内容应该为您提供更好的示例,说明如何使用continuation以及如何处理这些continuation中的任务抛出的异常...
延续可以查明Task前提任务的异常属性是否由前提引发异常.以下内容将a的结果打印NullReferenceException到控制台
Task task1 = Task.Factory.StartNew (() => { throw null; });
Task task2 = task1.ContinueWith (ant => Console.Write(ant.Exception());
Run Code Online (Sandbox Code Playgroud)
如果task1抛出异常并且延迟没有捕获/查询此异常,则认为它未处理并且应用程序死亡.使用continuation,通过Status关键字建立任务结果就足够了
asyncTask.ContinueWith(task =>
{
// Check task status.
switch (task.Status)
{
// Handle any exceptions to prevent UnobservedTaskException.
case TaskStatus.RanToCompletion:
if (asyncTask.Result)
{
// Do stuff...
}
break;
case TaskStatus.Faulted:
if (task.Exception != null)
mainForm.progressRightLabelText = task.Exception.InnerException.Message;
else
mainForm.progressRightLabelText = "Operation failed!";
default:
break;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你不使用你的延续要么必须等待一个任务try/ catch块或查询任务的Result中try/ catch块
int x = 0;
Task<int> task = Task.Factory.StartNew (() => 7 / x);
try
{
task.Wait();
// OR.
int result = task.Result;
}
catch (AggregateException aggEx)
{
Console.WriteLine(aggEx.InnerException.Message);
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
| 归档时间: |
|
| 查看次数: |
7253 次 |
| 最近记录: |