繁体   English   中英

Process.Start 阻塞

[英]Process.Start is blocking

我正在调用 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 时如何解决此问题?


地狱新闻:

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

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

不, 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");
    }
}

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

创建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}.");
}

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

我在 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 的初始屏幕仍处于打开状态。

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

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

在此处输入图像描述

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

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

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

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

如果要启动进程,然后使进程独立于“启动器”/发起调用:

//Calling process
using (System.Diagnostics.Process ps = new System.Diagnostics.Process())
{
    try
    {
        ps.StartInfo.WorkingDirectory = @"C:\Apps"; 
        ps.StartInfo.FileName = @"C:\Program Files\Microsoft Office\Office14\MSACCESS.EXE"; //command
        ps.StartInfo.Arguments = @"C:\Apps\xyz.accdb"; //argument
        ps.StartInfo.UseShellExecute = false;
        ps.StartInfo.RedirectStandardOutput = false;
        ps.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
        ps.StartInfo.CreateNoWindow = false; //display a windows
        ps.Start();
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("==> Process error <=={0}" + ex.ToString(), Environment.NewLine));
    }
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM