【问题标题】:Process.Start in BackgroundWorker C#Process.Start 在 BackgroundWorker C#
【发布时间】:2013-04-06 18:43:26
【问题描述】:

我最糟糕的时间是围绕线程/后台进程。我的问题在某种程度上似乎很常见,但我还没有找到满足我需求的好例子。

经典的例子是这样的:
当某个长时间运行的任务/进程运行时,我的 UI 会冻结 - 我希望至少能够移动/最小化 UI。

经典回复包括线程和任务工厂以及 BackgroundWorker 解决方案。 但无论我如何实现它们,我都会得到糟糕的结果。

在我的程序中,我正在执行另一个应用程序并等待它完成。为了简单起见,假设我这样做:

            Process p = Process.Start("notepad.exe somefile.txt");
            p.WaitForExit();
            //read somefile.txt

很明显,当WaitForExit() 等待我关闭记事本时,我的应用程序 UI 会挂起。

我已经尝试了一些建议的方法来解决这个问题,但我被画到了两个角落之一:

  1. 我的界面仍然挂起,然后在我关闭记事本时读取 somefile.txt 就好了。
  2. 进程(记事本)运行良好,但我的应用程序在我关闭记事本之前立即读取 somefile.txt(所以我猜它是异步运行的)

我看到的大多数例子都涉及到一个很大的数字 - 简单但不是我正在做的事情。启动这个“外部”过程会使事情变得有点复杂。

感谢您的时间和考虑!!

【问题讨论】:

  • 如果您在后台线程上执行此操作,那么您的 UI 将不会挂起,因为您正在等待其他线程而不是 UI 线程。
  • 您需要显示其余代码,显示将启动记事本的最小程序,使用后台工作程序,但仍然挂起。
  • 您是否尝试过使用 BackgroundWorker 并在 worker 的 AfterCompleted 处理程序中读取 somefile.txt?
  • Rohit 你是对的,UI 没有挂起,但应用程序继续运行,就好像“somefile.txt”被编辑一样。我需要能够在后台进程运行时与 UI 交互(将其移开),但在进程完成之前不能“继续”。对不起,如果那是模糊的
  • 您应该考虑使用msdn.microsoft.com/en-us/library/…(在文件更改时处理事件)而不是使用WaitForExit。

标签: c# multithreading process waitforexit


【解决方案1】:

BackgroundWorker 在这里似乎很合适;它应该按照这些思路进行配置:

var worker = new BackgroundWorker();
worker.WorkerReportsProgress = false;
worker.WorkerSupportsCancellation = false;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();

然后你有处理程序:

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    //start notepad process here.
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //read somefile.txt here.
}

【讨论】:

  • 那么,我如何(例如)将文件名传递给worker_DoWork方法_我真的在这里显示我的经验不足。
  • 我认为您仍然需要worker_DoWork 处理程序中的p.WaitForExit()
  • 另外...假设我在 worker.RunWorkerAsync(); 之后有代码这对文本文件的内容做了一些事情。在我的代码中,即使它没有被更新,它也会继续前进
  • 你需要把它放在RunWorkderCompleted 处理程序中(刚刚注意到代码中的拼写错误......对此感到抱歉)
  • 我在 DoWork 中确实有 waitForexit,但它挂起了 UI
【解决方案2】:

从事情的声音来看,您的应用程序没有在单独的线程上运行 Process.WaitForExit 调用,否则不会有任何挂起。

BackgroundWorkerThreadThreadPool 都是有用的工具,但它们可能难以使用且难以正确使用,带有 System.Threading.Task 的任务并行库在某种程度上已经“取代”了直接使用线程对于大多数需要异步执行的操作。

见:Threads and the new Task library in C#

所以你的代码变成了。

Task.Factory.StartNew(() =>
{
   var proc = new Process("...");
   proc.WaitForExit();
   File.Read("...");
});

【讨论】:

  • 谢谢克林特让我看看我能不能试试这个。在这种情况下,是否可以将 File.Read 放在任务工厂代码之外? -我的例子很简单。
  • 所以.. 这让我陷入了困境 2。我的流程运行良好,但此任务工厂之后的代码立即运行。对不起,如果我含糊其辞。顺便说一句,我认为您缺少一个 );在最后一行。
  • System.Threading.Task 命名空间非常棒 - 需要注意的是,它在 .net 框架的早期版本中不可用(我认为出现在 4.0 中)。
  • 正在运行 4。这似乎是一种非常简单的方法,但任务会自行完成,我的应用程序会朝着其他方向发展
  • @FredB 这就是多线程和异步的重点,不是吗?能够与其他东西同时运行?如果您想等待任务完成,您可以使用.Wait 方法,但随后您将再次挂起主线程并破坏使用后台线程的目的......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多