C# WPF从主线程停止后台工作
我有一个后台工作人员,在后台执行工作。该工作在命令提示符下运行某个.exe应用程序,并等待显示输出。有时.exe应用程序是堆栈式的,或者需要花费很多时间。我想在一分钟后让工人停下来,以防它仍在运行。 问题是我有一个进度条,在主线程中运行1分钟。我想在主线程(UI)的进度条已满(1分钟后)时停止工作进程。这是我的密码:C# WPF从主线程停止后台工作,c#,wpf,multithreading,C#,Wpf,Multithreading,我有一个后台工作人员,在后台执行工作。该工作在命令提示符下运行某个.exe应用程序,并等待显示输出。有时.exe应用程序是堆栈式的,或者需要花费很多时间。我想在一分钟后让工人停下来,以防它仍在运行。 问题是我有一个进度条,在主线程中运行1分钟。我想在主线程(UI)的进度条已满(1分钟后)时停止工作进程。这是我的密码: private void btnTest_Click(object sender, RoutedEventArgs e) { wTest = ne
private void btnTest_Click(object sender, RoutedEventArgs e)
{
wTest = new BackgroundWorker();
wTest .DoWork += new DoWorkEventHandler(wTest _DoWork);
wTest .RunWorkerCompleted += wTest _RunWorkerCompleted;
wTest .WorkerReportsProgress = true;
wTest .WorkerSupportsCancellation = true;
wTest .RunWorkerAsync();
while (pbTest.Value < 91)
{
if (!wTest.CancellationPending)
{
pbTest.Value = (pbTest.Value + 100/60);
Thread.Sleep(1000);
}
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background,
new ThreadStart(delegate { }));
}
}
void wTest_DoWork(object sender, DoWorkEventArgs e)
{
//call .exe application and wait for output
}
private void btnTest\u单击(对象发送方,路由目标)
{
wTest=新的BackgroundWorker();
wTest.DoWork+=新的DoWorkEventHandler(wTest\U DoWork);
wTest.RunWorkerCompleted+=wTest\u RunWorkerCompleted;
wTest.WorkerReportsProgress=true;
wTest.workersupport扫描单元=真;
wTest.RunWorkerAsync();
而(pbTest.Value<91)
{
如果(!wTest.CancellationPending)
{
pbTest.Value=(pbTest.Value+100/60);
睡眠(1000);
}
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background,
新线程开始(委托{});
}
}
void wTest_DoWork(对象发送方,DoWorkEventArgs e)
{
//调用.exe应用程序并等待输出
}
我该怎么做?您需要做的是让您的
DoWork
代表检查e.Cancel
(在DoWorkEventArgs
中)属性设置为true
。如果DoWork
被阻塞,比如等待StandardOutput
,那么这根本不可能
另一种方法是传递进程。WaitForExit
一个int
说明它应该等待输出多长时间:
process.WaitForExit(60000);
如果您使用的是.net 4.5,则可以使用
任务
类和关联的取消toksource
和取消令牌
类。请注意,任务支持通过IProgress
界面报告进度。斯蒂芬·克利里对此很在行
如果您正在执行的工作没有提供异步接口,您可以使用任务。运行执行它,并传递取消令牌以监视取消。在您执行工作时,您需要监视令牌的取消。一种方法是调用,如果在CancellationTokenSource
上调用了Cancel
,则调用将抛出operationcanceledexception
CancellationTokenSource
还支持在特定时间后取消,这对于您的场景来说非常方便
private CancellationTokenSource cts;
private void btnTest_Click(object sender, RoutedEventArgs e)
{
if(cts == null)
{
cts = new CancellationTokenSource(new TimeSpan(0, 0, 60)); // cancel after 60 seconds
}
await Task.Run( () => Work(), cts.Token);
cts = null;
}
void Work(CancellationToken token)
{
// do work
token.ThrowIfCancellationRequested();
// do work
}
您需要做两件事才能取消您的后台工作人员的工作。首先,您需要检查DoWork
处理程序方法中的:
private void wTest_DoWork(object sender, DoWorkEventArgs e)
{
//call .exe application and wait for output
if (worker.CancellationPending)
{
e.Cancel = true;
}
}
然后,当您想要取消工作时,您应该在您的后台工作人员中调用此选项:
backgroundWorker.CancelAsync();
但是,由于您没有按预期使用BackgroundWorker
,因此我认为这对您不起作用。如果您正在等待第三方应用程序启动,则无法将e.Cancel
属性设置为true
老实说,我不太明白你为什么要用一个后台工作人员来启动一个流程。Process.Start
方法不需要花费时间来完成,因为它不等待任何响应。在我看来,您最好监视并调用。停止后台工作程序或停止它启动的进程?我想停止工作程序。我可以估计它也会停止进程吗?我正在使用.NET3.5。这个类包含在.NET 4Ok中,我要说的是,我的答案是针对.NET 4.5的。有什么方法可以为.NET 3.5实现它吗?不是使用async
和wait
,但是如果您想使用任务并行库,您可以为.NET 3.5尝试这个端口。但如果可以,最好升级到.NET4.0或4.5。这给了你更多的选择