对于 C# 来说相对较新。我制作了一个 Windows 窗体来监视文件中的更改。该程序占用了我 30% 的 CPU,我想让它运行得轻一点。运行诊断会话后,我可以看到 Run() 使用了几乎一半的程序资源。有什么办法可以优化这个吗?
static void Run()
{
using (FileSystemWatcher watcher = new FileSystemWatcher())
{
watcher.Path = Path.GetDirectoryName(path);
watcher.Filter = Path.GetFileName(path);
watcher.Changed += OnChanged;
watcher.Renamed += OnRenamed;
watcher.EnableRaisingEvents = true;
Debug.WriteLine("Running Reader");
while (!cts.Token.IsCancellationRequested) ;
}
}
这是我的CPU使用情况。
我的关闭线程的脚本也相当繁重,使用了近 30%
static CancellationTokenSource cts = new CancellationTokenSource();
private async void buttonRun_Click(object sender, EventArgs e)
{
buttonRun.Enabled = false; // Disable the button to prevent multiple clicks
listBoxStatus.Items.Add($"Line Reader Started! \t Time: {DateTime.Now}");
listBoxStatus.Items.Add("");
status = "Running";
statusApplier();
try
{
await Task.Run(() =>
{
LogApplicationStart();
LoadComparisonFileLines();
Run();
}, cts.Token);
}
catch (OperationCanceledException)
{
listBoxStatus.Items.Add($"Task was cancelled! \t Time: {DateTime.Now}");
}
catch (Exception ex) // Catch any other exceptions
{
listBoxStatus.Items.Add($"An error occurred: {ex.Message}");
}
finally
{
cts.Dispose(); // Dispose the CancellationTokenSource
cts = new CancellationTokenSource(); // Reset the token source
buttonRun.Enabled = true; // Enable the button after the task is completed or if an error occurs
if (listBoxStatus.Items.Count > 0 && listBoxStatus.Items[listBoxStatus.Items.Count - 1].ToString().Contains("Change"))
{
listBoxStatus.Items.Add("");
}
listBoxStatus.Items.Add($"Line Reader Ended! \t Time: {DateTime.Now}");
listBoxStatus.Items.Add("");
status = "Stopped";
statusApplier();
LogApplicationEnd();
}
}
private void buttonStop_Click(object sender, EventArgs e)
{
cts.Cancel(); // Cancel the task
}
我非常感谢任何帮助。 谢谢
我不知道如何比我已经使用的 FileSystemWatcher 更有效地使用它
造成CPU占用率高的罪魁祸首就是while循环,而事实上,程序中不应该存在这种几乎无穷无尽的空循环。
代码最简单的解决方案是将此循环替换为
cts.WaitHandle.WaitOne();
但是您的代码还有另一个问题。您的逻辑是使用一个按钮开始观看,使用另一个按钮停止观看,因此您应该将
finally
部分和处理 FileSystemWatcher
的部分放在停止按钮的回调中。这个CancellationTokenSource
是多余的。