對不起,是我的錯。請先在下面閱讀我的答案。
這是一個winform程式(.net6)。在開始時,或單擊主表單上的按鈕時,應在后臺運行一個 bat 檔案。蝙蝠運行 10~120 分鐘,所以我不想等待它完成。所以winform應該會正常繼續,等待用戶操作。
但它沒有。shell的黑色視窗停留在前面,winform只有在行程完成后才開始回應。
以下是代碼:
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.
}
嘗試的解決方案:
啟動行程并允許呼叫者結束而不等待行程完成表示 UseShellExecute = true 應該使 Process.Start() 在后臺運行。但它沒有。
C# 執行緒/異步:在 UI 可互動時在后臺運行任務說 Task.Run((Action) MyFunction); 無需等待將使其繼續,但不是。
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~
uj5u.com熱心網友回復:
由于您已經使用了 async ,因此async Task RunCmdAsync()您應該至少在函式內使用await一次。
uj5u.com熱心網友回復:
您可以嘗試在另一個執行緒中運行 Bat 檔案,它會防止表單凍結。
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
}
}
}
uj5u.com熱心網友回復:
經過更多的作業,我意識到它已經開始作業了(無需等待即可繼續)。但是它啟動的任務有 10 個執行緒(我的筆記本電腦總共有 12 個),所以它占用了大部分 CPU,主執行緒很慢,好像在等待一樣。
為了讓它更好地作業,我做了一個機制:
- 與其立即開始任務,不如留下一個“待辦事項”標志。
- 繼續,直到一切正常(對我來說,當 winform 空閑時)。
- 檢查是否有“待辦事項”標志。
- 如果是,請立即開始任務并留下“正在執行”標志。
- 繼續檢查任務是否完成,直到我們得到結果。
- 需要時清除所有標志。
以下代碼中的名稱是區分不同任務的標識。
public static class SimpleFlow
{
public enum Steps
{
Todo, Doing, Done
}
public static void CreateTag(Steps step, string name)
{
var tagFileName = TagFileName(step, name);
if (!File.Exists(tagFileName))
File.Create(tagFileName);
}
public static bool ExistsTag(Steps step, string name)
{
var tagFileName = TagFileName(step, name);
return File.Exists(tagFileName);
}
public static void DeleteTag(Steps step, string name)
{
var tagFileName = TagFileName(step, name);
if (File.Exists(tagFileName))
File.Delete(tagFileName);
}
public static void ClearTags(string name)
{
foreach (var step in Enum.GetValues<Steps>())
{
DeleteTag(step, name);
}
}
private static string TagFileName(Steps step, string name)
{
var tagFileName = $@"{Directory.GetCurrentDirectory()}\_{step}_{name}.tag";
return tagFileName;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/456219.html
