我有一个BackgroundWorker,可以在后台执行工作。工作是在命令提示符下运行一些.exe应用程序并等待输出显示。有时.exe应用程序是堆栈或需要很多时间。我想在一分钟后停止工人,以防它仍在运行。 问题是我有一个在主线程中运行1分钟的进度条。我想在主线程(UI)>中进度条已满(1分钟后)时停止工作。这是我的代码:
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
}
我该怎么做?
答案 0 :(得分:1)
如果您使用的是.net 4.5,则可以使用Task
类以及相关的CancellationTokeSource
和CancellationToken
类。请注意,任务支持通过IProgress
界面报告进度。 Stephen Cleary对此有一个很好的example。
如果您正在进行的工作不提供异步接口,您可以使用Task.Run
执行它并传递CancellationToken
以监控取消。当您正在进行工作时,您需要监视令牌以进行取消。一种方法是拨打ThrowIfCancellationRequested,如果在OperationCancelledException
上调用了Cancel
,则会CancellationTokenSource
。 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
}
答案 1 :(得分:1)
您需要做两件事才能取消BackgroundWorker
的工作。首先,您需要检查DoWork
处理程序方法中的BackgroundWorker.CancellationPending
property:
private void wTest_DoWork(object sender, DoWorkEventArgs e)
{
//call .exe application and wait for output
if (worker.CancellationPending)
{
e.Cancel = true;
}
}
然后,当您想要取消工作时,您应该在BackgroundWorker
:
backgroundWorker.CancelAsync();
但是,由于您不使用BackgroundWorker
因为它本来要使用,我不认为这对您有用。如果您正在等待第三方应用程序启动,则您将无法将e.Cancel
属性设置为true
。
说实话,我不太明白为什么你只使用BackgroundWorker
开始一个过程。 Process.Start
方法没有时间完成,因为它不等待任何响应。在我看来,您最好不要监控Process.Exited
event并改为调用Process.Kill
method。
答案 2 :(得分:0)
您需要做的是DoWork
代理检查e.Cancel
(DoWorkEventArgs
)属性设置为true
。如果DoWork
正在阻止,例如等待StandardOutput
,那么根本就不可能。
另一种方法是传递Process.WaitForExit
和int
说明它应该等待输出的时间:
process.WaitForExit(60000);