0

我有一个代码应该启动一个进程以渲染动画。它工作得很好,可以启动进程和所有进程,但是当进程运行时,我的程序说没有响应,并冻结拒绝更新进度。

这是应该导致问题的代码:

void Render()
{
    while (currentFrame <= lastFrame)
    {
        bool rendering = IsRendering("cmd");

        if (rendering == false)
        {
            StreamWriter renderBatch = new StreamWriter(batchFile);
            renderBatch.Write('"' + renderPathField.Text + '"' + " -rd " + '"' + imagePath.Text + '"' + " -s " + currentFrame + " -e " + currentFrame + " " + '"' + sceneFile.Text + '"');
            renderBatch.Close();

            var renderProcess = new Process();
            renderProcess.StartInfo = new ProcessStartInfo(batchFile);
            //renderProcess.StartInfo.Arguments = '"' + renderPathField.Text + '"' + " -rd " + '"' + imagePath.Text + '"' + " -s " + currentFrame + " -e " + currentFrame + " " + '"' + sceneFile.Text + '"';
            renderProcess.StartInfo.UseShellExecute = false;
            //renderProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            renderProcess.Start();

            if (renderProcess.HasExited == true && currentFrame < lastFrame)
            {
                ProgressBar1.Value = (currentFrame - 1) / lastFrame;
                currentFrame++; //goes onto the next frame once it is done rendering this frame
            }
        }
    }
}

这是它所在的完整代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
//using System.Net;
using System.Diagnostics;
using System.IO;

namespace Maya_Network_Render
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Globals ///////////////////////////////////////
        string prefFile = "C:\\Program Files\\Maya Render Buddy Preferences\\options.txt";
        string batchFile = "C:\\Program Files\\Maya Render Buddy Preferences\\render.bat";
        int firstFrame;
        int lastFrame;
        int currentFrame;
        // Globals //////////////////////////////////////

        private void Form1_Load(object sender, EventArgs e)
        {
            if (Directory.Exists("C:\\Program Files\\Maya Render Buddy Preferences"))
            {
                if (File.Exists(prefFile))
                {
                    StreamReader preferences = new StreamReader(prefFile);
                    string renderFilePath = preferences.ReadLine();
                    renderPathField.Text = renderFilePath;
                    preferences.Close();
                }

                else
                {
                    File.Create(prefFile);
                }

            }

            else
            {
                Directory.CreateDirectory("C:\\Program Files\\Maya Render Buddy Preferences");
                File.Create(prefFile);
            }
        }

        private void sceneBrowse_Click(object sender, EventArgs e)
        {
            OpenFileDialog scenefinder = new OpenFileDialog();
            scenefinder.Title = "Browse to your Maya scene file";
            scenefinder.RestoreDirectory = true;
            if (scenefinder.ShowDialog() == DialogResult.OK)
            {
                sceneFile.Text = scenefinder.FileName;
            }
        }

        private void imageBrowse_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog imageFolderSelection = new FolderBrowserDialog();
            imageFolderSelection.ShowDialog();
            imagePath.Text = imageFolderSelection.SelectedPath;
        }

        private void renderButton_Click(object sender, EventArgs e)
        {
            string imageSavePath = imagePath.Text;
            string scene = sceneFile.Text;

            try
            {
                if (FirstFrameTextbox.Text != "" && LastFrameTextBox.Text != "") // if the textboxes are filled in then assign them to a variable
                {
                    firstFrame = Convert.ToInt32(FirstFrameTextbox.Text);
                    lastFrame = Convert.ToInt32(LastFrameTextBox.Text);

                    if (File.Exists(scene))
                    {
                        if (File.Exists(batchFile))
                        {
                            currentFrame = firstFrame;
                            progressMessage.Text = " Rendering Frame " + currentFrame + " of " + lastFrame + " from " + scene;
                            Render();
                        }

                        else
                        {
                            File.Create(batchFile); // if there is no batch file then we make one!
                            currentFrame = firstFrame;
                            progressMessage.Text = " Rendering Frame " + currentFrame + " of " + lastFrame + " from " + scene;
                            Render();
                        }
                    }

                    else // if there is not a scene file we let the user know that
                    {
                        MessageBox.Show("Please fill in image path, project path and scene file", "Cannot find file");
                        progressMessage.Text = " ERROR! SCENE FILE OR IMAGE PATH IS MISSING";
                    }
                }

                else
                {
                    MessageBox.Show("The numbers entered into the first or last frame fields are invalid", "invalid frame range");
                }
            }

            catch (Exception f)
            {
                MessageBox.Show(f.ToString() + "                                                                                                                                                                                                                                                                                                                                                                 Most commonly errors result non numerical input in the frame entry fields", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }

        }

        private void ChangeRenderPath_Click(object sender, EventArgs e)
        {
            OpenFileDialog renderfinder = new OpenFileDialog();
            renderfinder.Title = "Browse to your Render.exe file";
            renderfinder.RestoreDirectory = true;
            if (renderfinder.ShowDialog() == DialogResult.OK)
            {
                StreamWriter preferences = new StreamWriter(prefFile);
                renderPathField.Text = renderfinder.FileName;
                preferences.Write(renderPathField.Text);
                preferences.Close();
            }
        }

        public bool IsRendering(string processName)
        {
            foreach (Process renderProcess in Process.GetProcesses())
            {
                if (renderProcess.ProcessName.Contains(processName))
                {
                    return true;
                }
            }
            return false;
        }

        void Render()
        {
            while (currentFrame <= lastFrame)
            {
                bool rendering = IsRendering("cmd");

                if (rendering == false)
                {
                    StreamWriter renderBatch = new StreamWriter(batchFile);
                    renderBatch.Write('"' + renderPathField.Text + '"' + " -rd " + '"' + imagePath.Text + '"' + " -s " + currentFrame + " -e " + currentFrame + " " + '"' + sceneFile.Text + '"');
                    renderBatch.Close();

                    var renderProcess = new Process();
                    renderProcess.StartInfo = new ProcessStartInfo(batchFile);
                    //renderProcess.StartInfo.Arguments = '"' + renderPathField.Text + '"' + " -rd " + '"' + imagePath.Text + '"' + " -s " + currentFrame + " -e " + currentFrame + " " + '"' + sceneFile.Text + '"';
                    renderProcess.StartInfo.UseShellExecute = false;
                    //renderProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                    renderProcess.Start();

                    if (renderProcess.HasExited == true && currentFrame < lastFrame)
                    {
                        ProgressBar1.Value = (currentFrame - 1) / lastFrame;
                        currentFrame++; //goes onto the next frame once it is done rendering this frame
                    }
                }
            }
        }

        private void Form1_FormClosing_1(object sender, FormClosingEventArgs e)
        {
            if (DialogResult.No == MessageBox.Show("If this program is not open it will not assign renders. Would you still like to close?", "You are about to stop rendering!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation))
            {
                e.Cancel = true;
            }

            else
            {
                foreach (Process renderProcess in Process.GetProcesses())
                {
                    if (renderProcess.ProcessName.Contains("cmd"))
                    {
                        renderProcess.Kill();
                    }
                }
            }
        }
    } // form closing brace
}
4

1 回答 1

3

UI updates need to happen on a different thread than the main process, otherwise it will wait until the entire process is complete before showing you the updated UI.

Since you have a lot of "process" code inside your form there's not a simple fix - you will need to start the processing in another thread and set up events to pass updates back to the UI.

于 2013-10-23T19:49:19.403 回答