gpt4 book ai didi

.net - 如何等待取消的任务完成?

转载 作者:行者123 更新时间:2023-12-02 13:48:03 24 4
gpt4 key购买 nike

当谈到使用 .NET 4.0 进行并行编程时,我显然不知道自己在做什么。我有一个简单的 Windows 应用程序,它启动一个任务来执行一些无需动脑子的工作(输出数字 1-1000)。我在中途暂停了一段时间来模拟一个长时间运行的过程。当发生长时间暂停时,如果我点击“停止”按钮,其事件处理程序将调用 CancellationTokenSource 的 Cancel 方法。我不想在“停止”按钮的事件处理程序中进行任何进一步的处理(在本例中为输出消息),直到取消的任务完成其当前迭​​代。我该怎么做呢?我尝试在“停止”按钮的事件处理程序中使用 Task.WaitAll 等,但这只会引发未处理的 AggregateException。如果按上述方式运行,以下代码将有助于解释我的问题:

  private Task t;
private CancellationTokenSource cts;

public Form1()
{
InitializeComponent();
}

private void startButton_Click(object sender, EventArgs e)
{
statusTextBox.Text = "Output started.";

// Create the cancellation token source.
cts = new CancellationTokenSource();

// Create the cancellation token.
CancellationToken ct = cts.Token;

// Create & start worker task.
t = Task.Factory.StartNew(() => DoWork(ct), ct);
}

private void DoWork(CancellationToken ct)
{
for (int i = 1; i <= 1000; i++)
{
ct.ThrowIfCancellationRequested();

Thread.Sleep(10); // Slow down for text box outout.
outputTextBox.Invoke((Action)(() => outputTextBox.Text = i + Environment.NewLine));

if (i == 500)
{
Thread.Sleep(5000);
}
}
}

private void stopButton_Click(object sender, EventArgs e)
{
cts.Cancel();

Task.WaitAll(t); // this doesn't work :-(

statusTextBox.Text = "Output ended.";
}

private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}

对此的任何帮助将不胜感激。提前致谢。

最佳答案

您通常只需使用 Task.Wait (而不是 WaitAll ),因为它是单个任务。然后适本地处理异常:

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.";
}

当您取消Task时,OperationCanceledException将被包裹成 AggregateException一打电话Wait()就被扔了或尝试获取任务的 Result (如果是 Task<T> )。

<小时/>

仅供您引用 - 这是一个地方,特别是考虑到您在这里所做的事情,C# 5 简化了事情。使用新的异步支持,您可以将其编写为:

// 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();
}

关于.net - 如何等待取消的任务完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11997166/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com