簡體   English   中英

c# 高效使用Process.start()

[英]c# Using Process.start () efficiently

下面是一段代碼,這段代碼將兩個文件連接起來生成另一個文件。

foreach (string jpegfile in files)
{
    string fileName = jpegfile + ".dcm";
    string ConfigFile =GetFileNameWithoutExtension(jpegfile) + ".cfg";
    string destFile = System.IO.Path.Combine(DirectoryPath, fileName);
    string command = "/C " + batFileName + " -C " + patientConfigFile + " " + jpegfile + " " + destFile;
    try
    {
        System.Diagnostics.Process process = new System.Diagnostics.Process();
        process.StartInfo.UseShellExecute = false;
        // You can start any process, HelloWorld is a do-nothing example.
        process.StartInfo.FileName = "cmd.exe";
        process.StartInfo.Arguments = command;
        process.StartInfo.CreateNoWindow = true;


        process.Start();

        process.WaitForExit();

        this.counter++;

        // Report progress as a percentage of the total task.
        int percentComplete =
        (int)((float)this.counter / (float)form.sumofImages * 100);
        if (percentComplete > highestPercentageReached)
        {
            highestPercentageReached = percentComplete;
            worker.ReportProgress(percentComplete);
        }

     }
     catch (Exception exp)
     {
         MessageBoxButtons buttons = MessageBoxButtons.OK;
         DialogResult result;
         result = MessageBox.Show("Batch File execution error " + exp, "Warning", buttons);
     }
}

我的問題是,如果我在 start() 之后使用 waitforexit() 我的代碼需要很長時間。 我怎樣才能加快上述循環?

如果您不必等待前一個文件到結束你開始下一個之前,你可以嘗試這樣的事:

// for each file, spawn a task to do your processing
var tasks = (from jpegfile in files
            select Task.Run(() =>
            {
                 // set up your process here...
                 process.Start();
                 // task won't be done until process exits
                 process.WaitForExit();
            }).ToArray();
// Wait for all the tasks to be done
Task.WaitAll(tasks);

您可以生成一堆任務並執行 Task.WaitAll,如 Matt Burland 的回答所示。

其他一些選項如下。 (我還沒有對這些進行徹底的測試,所以你可能想要這樣做)。 首先,您可以使用事件代替 WaitForExit:

private int counter = 0;
    int sumOfImages = 10; // Set this to the number of files

    private void ProcessStart(List<string> files)
    {
        foreach (string file in files)
        {
            Process process = new Process();
            process.StartInfo.UseShellExecute = false;
            // You can start any process, HelloWorld is a do-nothing example.
            process.StartInfo.FileName = "cmd.exe";
            process.StartInfo.Arguments = "someCommand";
            process.StartInfo.CreateNoWindow = true;
            process.EnableRaisingEvents = true;
            process.Exited += Process_Exited;

            process.Start();
        }
    }

    private void Process_Exited(object sender, EventArgs e)
    {
        int result = Interlocked.Increment(ref counter);

        int percentComplete = ((result / sumOfImages) * 100);

        worker.ReportProgress(percentComplete);
    }

如果您願意,您可以將整個內容放在線程池中。 我實際上喜歡將其作為答案 - 受 CPU 限制的部分是創建和啟動進程,這會將其放在后台線程上,因此它不會掛起您的 UI。 它將消除等待結果的開銷,這不受 CPU 限制。

這是一個插圖。 假設你去一家有 10 個人的餐廳。 當服務員來的時候,10個人中有9個人已經准備好點菜了。 服務員碰巧先問那個人點菜。 這時候,一桌人要么等着他做決定,要么服務生接受其他9人點的菜,然后回到第一個人。 很可能在原來的服務員接受其他 9 個訂單時,引入一個額外的服務員來等待第一個人的訂單是毫無意義的。 如果絕對必要,服務員可以將 9 個訂單帶到廚房,然后再回來接受第一個人的訂單。

重點是,如果只是等待其中一個帶來額外服務員的人的結果,並不一定會給您帶來很大的性能提升。

顯然,在這個比喻中,服務員是一個線程,而人是需要完成的任務。 在上面的解決方案中,你有一個服務員(線程池線程)為所有的人服務(創建所有的進程),然后這些人(進程)告訴他他們什么時候准備好點菜(即進程提出事件)。 然后他告訴廚房他們的訂單(在 Worker 上引發 ReportProgress 事件)。

另一種選擇是 Parallel.ForEach 循環:

private void ProcessStart(List<string> files)
    {
        int sumOfImages = files.Count;
        int count = 0;
        string command = "";

        Parallel.ForEach(files,
            delegate (string file)
            {
                Process process = new Process();
                process.StartInfo.UseShellExecute = false;
                // You can start any process, HelloWorld is a do-nothing example.
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.Arguments = command;
                process.StartInfo.CreateNoWindow = true;

                process.Start();

                process.WaitForExit();

                int result = Interlocked.Increment(ref count);

                int percentComplete = ((result / sumOfImages) * 100);

                worker.ReportProgress(percentComplete);
            });
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM