搜索启动后UI控件3-6秒无响应的问题排查求助
搜索启动后UI控件3-6秒无响应的问题排查求助
大家好,我最近做了一个文件内容搜索工具,遇到了一个奇怪的UI卡顿问题,想请各位帮忙分析下:
当点击启动搜索按钮后,前3-6秒内界面上的按钮(比如暂停、取消)完全不响应鼠标操作,但程序并没有真的冻结——后台的搜索逻辑还在正常运行,过了这段时间后所有控件又能正常响应了。
以下是按钮点击事件的核心代码:
private async void BtnStart_Click(object sender, EventArgs e) { if (isSearching) return; ClearLog(); string path = txtFolderPath.Text.Trim(); string keywordInput = txtKeyword.Text.Trim(); string extension = comboExtensions.SelectedItem?.ToString(); bool includeSub = chkSubfolders.Checked; bool showErrors = chkShowErrors.Checked; if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(keywordInput) || !Directory.Exists(path)) { Log("Invalid path or keyword.", Color.Red); return; } string[] rawTerms = keywordInput.Split(new[] { "⬌" }, StringSplitOptions.None); var keywordList = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (string raw in rawTerms) { string term = raw.Trim(); if (!string.IsNullOrEmpty(term)) keywordList.Add(term); } if (keywordList.Count == 0) { Log("No valid search terms found.", Color.Red); return; } isSearching = true; cts = new CancellationTokenSource(); startTime = DateTime.Now; elapsedTimer.Start(); btnStart.Enabled = false; btnPauseResume.Enabled = true; btnCancel.Enabled = true; Log("Search started...", Color.Yellow); Log($"Path: {path}", Color.Gray); Log($"Extensions: {extension}", Color.Gray); Log($"Terms: {string.Join(", ", keywordList)}", Color.Gray); Log($"Subfolders: {(includeSub ? "Yes" : "No")}, Errors: {(showErrors ? "Shown" : "Hidden")}", Color.Gray); totalFiles = 0; scannedFiles = 0; matchCount = 0; // Offload file enumeration to a background thread List<string> files = await Task.Run(() => GetFiles(path, extension, includeSub)); totalFiles = files.Count; lblTotalFiles.Text = $"Total files: {totalFiles}"; await Task.Run(() => { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { var options = new ParallelOptions { CancellationToken = cts.Token, MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount / 2) }; Parallel.ForEach(files, options, (file) => { pauseEvent.Wait(); if (cts.Token.IsCancellationRequested || !isSearching) return; Interlocked.Increment(ref scannedFiles); BeginInvoke((Action)(() => { if (!isSearching) return; lblScannedFiles.Text = $"Scanned: {scannedFiles}/{totalFiles}"; if (scannedFiles > 0) { averageTimePerFile = stopwatch.Elapsed.TotalSeconds / scannedFiles; double estimatedRemainingTime = averageTimePerFile * (totalFiles - scannedFiles); lblEstimateTime.Text = $"Estimate: {estimatedRemainingTime:F0}s"; } })); try { string content = File.ReadAllText(file); int localMatches = 0; foreach (string term in keywordList) { int index = 0; while ((index = content.IndexOf(term, index, StringComparison.OrdinalIgnoreCase)) != -1) { localMatches++; index += term.Length; } } if (localMatches > 0) { Interlocked.Add(ref matchCount, localMatches); BeginInvoke((Action)(() => { if (!isSearching) return; Log($"✔ MATCH: {file}", Color.Green); })); } } catch (Exception ex) { if (showErrors) { BeginInvoke((Action)(() => { if (!isSearching) return; Log($"⚠ ERROR: {file} => {ex.Message}", Color.Red); })); } } }); } catch (OperationCanceledException) { if (isCancel) { BeginInvoke((Action)(() => { Log("Search cancelled during operation.", Color.DeepSkyBlue); btnStart.Enabled = true; })); isCancel = false; } } stopwatch.Stop(); if (!cts.Token.IsCancellationRequested) { BeginInvoke((Action)(() => { isSearching = false; elapsedTimer.Stop(); lblElapsedTime.Text = $"Elapsed: {(DateTime.Now - startTime).TotalSeconds:F0}s"; lblEstimateTime.Text = "Estimate: Done"; Log("", Color.Black); Log($"Search complete. Matches: {matchCount} at {DateTime.Now:HH:mm:ss}", Color.Cyan); btnStart.Enabled = true; btnPauseResume.Enabled = false; btnCancel.Enabled = false; })); } }); }
我已经尝试过优化UI更新频率,比如改成每扫描100个文件才触发一次BeginInvoke更新进度:
if (scannedFiles % 100 == 0) { BeginInvoke((Action)(() => { lblScannedFiles.Text = $"Scanned: {scannedFiles}/{totalFiles}"; averageTimePerFile = stopwatch.Elapsed.TotalSeconds / scannedFiles; double estimatedRemainingTime = averageTimePerFile * (totalFiles - scannedFiles); lblEstimateTime.Text = $"Estimate: {estimatedRemainingTime:F0}s"; })); }
但这个改动并没有解决前几秒的UI无响应问题。我也怀疑过是不是pauseEvent或者BeginInvoke的使用有问题,但奇怪的是只有搜索启动的前几秒会卡顿,之后全程都很流畅,控件响应也正常。
有没有大佬能帮我分析下可能的原因,或者给点排查方向?谢谢大家!
内容来源于stack exchange
相关产品推荐
相关产品推荐

