8

我正在调用 Process.Start,但它阻塞了当前线程。

pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");

// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
    Trace.TraceError("Unable to run process {0}.");
}

即使进程关闭,代码也不再响应。

但是 Process.Start 真的应该阻塞吗?这是怎么回事?

(进程正确启动)


using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

namespace Test
{
    class Test
    {
        [STAThread]
        public static void Main()
        {
            Thread ServerThread = new Thread(AccepterThread);
            ServerThread.Start();

            Console.WriteLine (" ---  Press ENTER to stop service ---");
            while (Console.Read() < 0) { Application.DoEvents(); }

            Console.WriteLine("Done.");
        }

        public static void AccepterThread(object data)
        {
            bool accepted = false;

            while (true) {
                if (accepted == false) {
                    Thread hThread = new Thread(HandlerThread);
                    accepted = true;
                    hThread.Start();
                } else
                    Thread.Sleep(100);
            }
        }

        public static void HandlerThread(object data)
        {
            ProcessStartInfo pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");

            Console.WriteLine("Starting process.");

            // Start process
            Process mProcess = new Process();
            mProcess.StartInfo = pInfo;
            if (mProcess.Start() == false) {
                Console.WriteLine("Unable to run process.");
            }
            Console.WriteLine("Still living...");
        }
    }
}

控制台输出为:

--- 按 ENTER 停止服务 --- 启动进程。


找到了:

[STA线程]

使 Process.Start 阻塞。我阅读了STAThread 和 Multithreading,但我无法将这些概念与 Process.Start 行为联系起来。

AFAIK, Windows.Form需要STAThread 。使用 Windows.Form 时如何解决此问题?


地狱新闻:

如果我重建我的应用程序,我一次运行应用程序时可以正常工作,但是如果我停止调试并再次重新启动,问题就会出现。

在没有调试器的情况下执行应用程序时不会出现问题。

4

5 回答 5

13

不,Process.Start不要等待子进程完成......否则您将无法使用重定向 I/O 等功能。

示例控制台应用程序:

using System;
using System.Diagnostics;

public class Test
{
    static void Main()
    {
        Process p = new Process { 
            StartInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe")
        };
        p.Start();
        Console.WriteLine("See, I'm still running");
    }
}

这会在我的盒子上打印“看,我还在跑步”,而我的盒子没有问题 - 它在你的盒子上做了什么?

于 2010-06-19T19:23:49.803 回答
7

创建ProcessStartInfo并将 UseShellExecute 设置为 false(默认值为 true)。您的代码应为:

pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");
pInfo.UseShellExecute = false;

// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
    Trace.TraceError("Unable to run process {0}.");
}

我遇到了同样的问题,直接从可执行文件创建进程启动可执行文件解决了这个问题。

于 2012-09-09T00:15:46.250 回答
1

我在 WinForms 应用程序中遇到了与原始海报相同的阻塞行为,因此我在下面创建了控制台应用程序以简化测试此行为。

Jon Skeet 的示例使用记事本,它只需要几毫秒即可正常加载,因此线程块可能会被忽视。我试图启动 Excel,这通常需要更长的时间。

using System;
using System.Diagnostics;
using static System.Console;
using System.Threading;

class Program {

    static void Main(string[] args) {

        WriteLine("About to start process...");

        //Toggle which method is commented out:

        //StartWithPath();  //Blocking
        //StartWithInfo();  //Blocking
        StartInNewThread(); //Not blocking

        WriteLine("Process started!");
        Read();
    }

    static void StartWithPath() {
        Process.Start(TestPath);
    }

    static void StartWithInfo() {
        var p = new Process { StartInfo = new ProcessStartInfo(TestPath) };
        p.Start();
    }

    static void StartInNewThread() {
        var t = new Thread(() => StartWithPath());
        t.Start();
    }

    static string TestPath =
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
        "\\test.xlsx";
}

调用两者StartWithPathStartWithInfo在控制台应用程序中阻止我的线程。在 Excel 初始屏幕关闭且主窗口打开之前,我的控制台不会显示“进程已启动”。

在此处输入图像描述

StartInNewThread将立即在控制台上显示这两条消息,而 Excel 的初始屏幕仍处于打开状态。

于 2016-06-15T20:23:08.163 回答
0

通过命令提示符启动服务器:

"C:\Program Files (x86)\IIS Express\iisexpress" /path:\Publish /port:8080

这可以访问操作系统树进程的子线程。

于 2019-09-12T12:17:13.557 回答
0

我们在启动位于不同域的网络驱动器上的 .bat 脚本时遇到了这个问题(我们有两个受信任的域)。我运行了一个远程 C# 调试器,果然 Process.Start() 无限期地阻塞了。

在 power shell 中以交互方式重复此任务时,会弹出一个安全对话框:

在此处输入图像描述

就解决方案而言,这是我们前进的方向。完成工作的人修改了域 GPO 以完成信任。

于 2017-11-11T02:35:04.867 回答