Pregunta

I have a code that is supposed to start a process in order to render animation. It works great and starts the process and all, but while the process is running, my program says not responding, and freezes refusing to update progress at all.

Here is the code that should be causing the issue:

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
            }
        }
    }
}

Here is the full code that it is in:

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
}
¿Fue útil?

Solución

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top