在我的项目中,通过导航更改的用户控件很少。控件之一运行任务。我是这样的:
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时,将执行。我看到消息,可以取消任务并接受取消请求。
但是,Printer1任务的当前状态仍为“ IsRunning”。 因此,如果我返回到该用户控件,则Task将再次启动,并且Application具有两个正在运行的相似任务。
我试过像这样在Factory下运行任务
Task Printer1 = Task.Factory.StartNew(() => PrinterPooler(lst_PrinterStruct, 0), cts.Token);
但是没有成功。 App仍然运行两个类似的任务。
PrinterPooler方法不同步。
我不明白哪里犯了错误。需要您的帮助。
答案 0 :(得分:1)
您必须将令牌传递到PrintPooler
方法中,然后在内部检查是否应取消令牌。
for(int i = 0; i < 10000; i++)
{
DoStuff();
cancelToken.ThrowIfCancellationRequested(); // if tasks end with this exception, it knows the work has been cancelled
}
取消任务不会停止执行,它只是向内部代码发出信号,表明应该结束,并根据执行停止的方式将任务状态设置为Cancelled / Faulted / RanToCompletion。
请注意,您需要将相同的令牌传递给Task和将其抛出的方法。
答案 1 :(得分:1)
关于此帖子How do I abort/cancel TPL Tasks?
您必须自己实现烛光状态。例如:
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();
希望有帮助。