I have a problem with my PictureBox after executing a process. At the time I call the process, that just executes a batch file, the PictureBox (displaying a GIF animation) freezes.
I want to click the button that starts the process and show the PictureBox displaying the GIF animation, and after the process is done I want to hide the PictureBox.
Does anyone know how to achieve this?
Here's my code:
// My executeCmdCommand
public void executeCmdCommand(string argument)
{
var arg0 = argument; // Path
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C " + arg0;
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
private void button1_Click(object sender, EventArgs e)
{
DisplayImage();
string cmdCom = @"C:\Users\Mim\Desktop\test.bat";
executeCmdCommand(cmdCom);
HideImage();
}
private void DisplayImage()
{
imageControl.Show();
//PictureBox imageControl = new PictureBox();
imageControl.Width = 400;
imageControl.Height = 400;
Bitmap image = new Bitmap(@"C:\Users\foobar\Desktop\loading.gif");
imageControl.Dock = DockStyle.Fill;
imageControl.Image = (Image)image;
Controls.Add(imageControl);
}
private void HideImage()
{
imageControl.Hide();
}
The problem lies on this line of code inside your executeCmdCommand()
function:
process.WaitForExit();
Take a look at what the documentation says about this method:
Process.WaitForExit Method | Microsoft Docs
Sets the period of time to wait for the associated process to exit, and blocks the current thread of execution until the time has elapsed or the process has exited. To avoid blocking the current thread, use the Exited event.
So, you should not call this method if you want the UI thread unblocked till the end of the external process execution. But if you still want to be warned when the process ends, then you can use the Exited
event as suggested on the documentation.
You can found an example of the use of the Exited
event, and another ideas, here:
Windows Form run external process without blocking UI - Stack Overflow
I would add only one thing to the answer that I've just linked: If you are going to hide your PictureBox inside the event handler called by the Process.Exited
event, you should set a reference of your Form
to the Process.SynchronizingObject
property (documentation), otherwise your event handler can (mostly probably) be executed on a thread different from your UI thread, causing an error when accessing anything from your Form
, including the controls.
The code could be like this:
using System.Diagnostics;
public void executeCmdCommand(string argument)
{
Process process = new System.Diagnostics.Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = $"/C {argument}";
process.StartInfo = startInfo;
process.EnableRaisingEvents = true;
process.SynchronizingObject = this;
process.Exited += (sender, e) => {
HideImage();
};
process.Start();
//process.WaitForExit();
}