在我的项目中,我很少有通过导航更改的用户控件。其中一个控件运行任务。我是这样做的:
public partial class uc_WorkingArea : UserControl
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token;
public uc_WorkingArea()
{
InitializeComponent();
this.Unloaded += uc_WorkingArea_Unloaded;
token = cts.Token;
Task Printer1 = Task.Run(() => PrinterPooler(lst_PrinterStruct, 0), cts.Token);
}
private void uc_WorkingArea_Unloaded(object sender, RoutedEventArgs e)
{
cts.Cancel();
if (token.CanBeCanceled)
{
MessageBox.Show("Can be canceled");
}
if (token.IsCancellationRequested)
{
MessageBox.Show("Canceled requested");
}
cts.Cancel();
MessageBox.Show("Status: " + Printer1.Status.ToString());
}
}
当我离开当前用户控件并切换到另一个uc_WorkingArea_Unloaded执行时。我看到消息,该任务可以取消并接受取消请求。
但是,打印机 1 任务的当前状态仍然是"正在运行"。因此,如果我返回到此用户控件,任务将再次启动,并且应用程序有两个正在运行类似的任务。
我尝试在工厂下运行任务,像这样
Task Printer1 = Task.Factory.StartNew(() => PrinterPooler(lst_PrinterStruct, 0), cts.Token);
但没有成功。应用仍运行两个类似的任务。
打印机池程序方法不异步。
我不明白哪里犯了错误。需要你们的帮助。
您必须将令牌传递到 PrintPooler
方法中,并在内部检查是否应该取消它。
for(int i = 0; i < 10000; i++)
{
DoStuff();
cancelToken.ThrowIfCancellationRequested(); // if tasks end with this exception, it knows the work has been cancelled
}
取消任务不会停止执行,它只会向内部的代码发出信号,指示它应该结束,并根据执行停止的方式将任务状态设置为"已取消/出错/RanToComplete"。
请注意,您需要将相同的令牌传递给 Task 和将引发它的方法。
关于这篇文章 如何中止/取消 TPL 任务?
你必须自己实现你的坎克条件。例如:
public partial class uc_WorkingArea : UserControl
{
public CancellationTokenSource cts = new CancellationTokenSource();
public CancellationToken token;
public Task Printer1;
public uc_WorkingArea()
{
token = cts.Token;
Printer1 = Task.Factory.StartNew(() =>
{
while (!token.IsCancellationRequested)
{
Console.WriteLine("run");
Application.DoEvents();
}
}, token);
}
}
取消通话:
uc_WorkingArea gc = new uc_WorkingArea();
for (int i = 0; i < 10; i++) //PASS SOME TIME
{
Application.DoEvents(); //CONSOLE SHOULD SPAM 'RUN' FROM TASK
Thread.Sleep(1);
}
gc.cts.Cancel(); //CANCEL CALL, WHILE LOOP END
if (gc.token.IsCancellationRequested)
{
Console.WriteLine("stop");
MessageBox.Show("Canceled requested");
}
gc.cts.Dispose();
gc.Printer1.Dispose();
希望对您有所帮助。