簡體   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