2012-12-31 80 views
5

我正在编写一个应用程序,其中有一个运行在BackgroundWorker中的进程。我想支持从用户界面取消,但我没有看到一个简单的方法来做到这一点。取消通过System.Diagnostics.Process.Start()启动的进程

Process实际上是一个相当长的运行命令行EXE。输出通过Progress.OutputDataReceived事件异步重定向,并用于向GUI报告进度。

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    using (var process = new Process()) 
    { 
     //... 

     process.Start() 

     //... 

     process.WaitForExit(); 
    } 
} 

private void CancelWorker() 
{ 
    worker.CancelAsync(); 
    // where to actually listen for the cancellation??? 
} 

似乎没有成为一个办法让过程“监听”从StandardInput主线程抛开任何输入,但是这是行不通的,除非应用程序本身会响应特定的输入中止。

有没有办法根据主线程的取消请求取消进程?

对于在运行的过程中的EXE的我,我可以叫Process.Close()退出无任何副作用的目的,但Process对象仅已知worker_DoWork()方法,所以我需要跟踪Process实例为取消目的...这就是为什么我希望有更好的方法。

(如果它很重要,我针对.NET 3.5的兼容性问题。)

+1

有你开始一个过程,一个BG工人理由吗?这通常是一个不需要很长时间的调用(程序启动可能需要一段时间才能加载,但这将在其自己的过程中)。 – keyboardP

+0

它实际上不是在后台工作,但是在自定义的异步方法中,BackgroundWorker似乎更容易描述这种情况。但原因是这是在后台线程中运行的更大进程的一部分。 – psubsee2003

+0

CancelAsync将无法工作,因为该线程在几毫秒内完成了其作业,除非在该DoWork方法中有重负载。尽管'using'是一种很好的做法,因为您需要能够从代码的其他地方访问'Process',您可以拥有一个类级变量来保存'Process'并调用'Process.Close'。只要记得在线程返回或不再需要该进程时在进程上调用Dispose。 – keyboardP

回答

3

对于合作消除,你需要听BackgroundWorker.CancellationPending in BackgroundWorker.DoWork 事件。

How to: Use a Background Worker

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    using (var process = new Process()) 
    { 
     //... 

     process.Start() 

     //... 
     while(true) 
     { 
      if ((sender as BackgroundWorker).CancellationPending && !process.HasExited) 
      { 
       process.Kill(); 
       break; 
      } 
      Thread.Sleep(100); 
     } 

     process.WaitForExit(); 
    } 
} 
+0

好的建议,但是因为'while(true)',循环永远不会退出,除非收到取消。我将它改为'while(!process.HasExited)',它完美的工作,谢谢。 – psubsee2003

-1

试试这个,这可能是帮助你,在简单的方法

private System.Threading.TimerCallback worker; 
private System.Threading.Timer workertimer ; 
private void worker_DoWork() 
{ 
    //You codes 
} 
private void StartWorker() 
{ 
    worker = new System.Threading.TimerCallback(worker_DoWork); 
    workertimer = new System.Threading.Timer(worker, null, 1000, 1000); 
} 

private void CancelWorker() 
{ 
    worker.Dispose(); 
} 
+2

我不明白,'处理'是如何在'Dispose'方法中被杀死的。它如何工作? – Tilak