It's a winform program (.net6). At the beginning, or when a button on mainform is clicked, a bat file should be run in the background. The bat runs for 10~120 minutes so I do not want to wait for it's completion. So the winform should continue normally, waiting for users' operations.
But it didn't. The black window of the shell stays in front, and the winform starts to response only after the process is finished.
Here are the codes:
public void SomeButtonClicked()
{
Task task = Task.Run((Action)RunStaticCodeCheck); //Does not work.
}
private static void RunStaticCodeCheck()
{
_currentCmdFileName = GenerateCmdFile(); //CmdFile is a bat with program-able parameters in it.
RunCmdAsync(); //Warning from ide: "because this call is not awaited, execution of current method continues before the call is completed." No, the current method does NOT continue.
}
private static string? _currentCmdFileName; //A bat file name generated programmatically.
private static async Task RunCmdAsync()
{
if (string.IsNullOrEmpty(_currentCmdFileName))
return;
var cmdFileName = _currentCmdFileName;
_currentCmdFileName = null;
//Run bat.
var cmdline = new ProcessStartInfo("CMD.exe", $"/C \"{cmdFileName}\"") // The "" does not work.
{
UseShellExecute = true //Does not work.
};
//Solution 1.
// await Task.Run(() => { Process.Start(cmdline); }); //Does not work.
//Solution 2.
Task.Run(() => { Process.Start(cmdline); }); //Does not work.
// Solution 3.
// Process.Start(cmdline); //Does not work.
// Solution 4.
// var process = Process.Start(cmdline);
// if (process != null)
// process.WaitForExitAsync(); //Does not work.
}
Solutions tried:
Start process and allow caller to end without waiting for process to finish says that UseShellExecute = true should make the Process.Start() running in background. But it did not.
C# Threading/Async: Running a task in the background while UI is interactable says Task.Run((Action) MyFunction); without waiting will make it continue, but not.
How to start an application without waiting in a batch file? says blank in path might make the bat file wait or something like that. I tried using "" to wrap the cmd file name, and it did not help.
Ironically, I found many questions asked how to wait for a process/cmdline until finished. I deleted everything from those answers, but my program is still waiting!
I think there might be 2 solutions: Run a method async-ly without waiting; let the Shell start a bat file without waiting.
Any help? Thanks~
CodePudding user response:
As you have used async on async Task RunCmdAsync()
you should use await inside the function at least once.
CodePudding user response:
You can try to run the Bat File in another Thread, It will prevent the form from freezing.
using System;
using System.Diagnostics;
using System.Threading;
namespace Program
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press any Key to Start the Thread ...");
Console.ReadKey();
// Creating the new thread
Thread batStart = new Thread(new ThreadStart(RunBat));
batStart.Start(); // Starting it
Console.WriteLine("Bat File Started! ....");
Console.ReadKey();
}
static void RunBat()
{
// make new process info with bat file
ProcessStartInfo bat = new ProcessStartInfo(@"E:\test.bat");
// to hide the window
bat.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(bat); // starting the prcoess
}
}
}