使用后台线程时有效显示文件状态
Posted
技术标签:
【中文标题】使用后台线程时有效显示文件状态【英文标题】:Efficiently display file status when using background thread 【发布时间】:2011-02-18 08:48:08 【问题描述】:使用后台线程时如何有效地显示文件的状态?
例如,假设我有一个 100MB 的文件:
当我通过线程执行以下代码时(仅作为示例),它会在大约 1 分钟内运行:
foreach(byte b in file.bytes)
WriteByte(b, xxx);
但是...如果我想更新用户,我必须使用委托从主线程更新 UI,下面的代码需要 - 永远 - 从字面上看,我不知道我还在等待多久,我创建了这篇文章甚至还没有完成 30%。
int total = file.length;
int current = 0;
foreach(byte b in file.bytes)
current++;
UpdateCurrentFileStatus(current, total);
WriteByte(b, xxx);
public delegate void UpdateCurrentFileStatus(int cur, int total);
public void UpdateCurrentFileStatus(int cur, int total)
// Check if invoke required, if so create instance of delegate
// the update the UI
if(this.InvokeRequired)
else
UpdateUI(...)
【问题讨论】:
【参考方案1】:不要在每个字节上更新 UI。仅每 100k 左右更新一次。
观察:
int total = file.length;
int current = 0;
foreach(byte b in file.bytes)
current++;
if (current % 100000 == 0)
UpdateCurrentFileStatus(current, total);
WriteByte(b, xxx);
【讨论】:
很奇怪,在我回到这个页面之前我就是这么想的 - 我会试一试看看......我的意思是每 1k 字节...... 同样使用Control.BeginInvoke
而不是Invoke
,这样工作线程就不必等待UI线程了。【参考方案2】:
您过于频繁地更新 UI —— 100MB 文件中的每个字节都会导致 1 亿次 UI 更新(每个都编组到 UI 线程)。
将您的更新分解为总文件大小的百分比,可能是 10% 甚至 5% 的增量。因此,如果文件大小为 100 字节,则将 UI 更新为 10、20、30 等。
【讨论】:
【参考方案3】:我建议您根据经过的时间进行更新,这样无论文件大小或系统负载如何,您都有可预测的更新间隔:
DateTime start = DateTime.Now;
foreach (byte b in file.bytes)
if ((DateTime.Now - start).TotalMilliseconds >= 200)
UpdateCurrentFileStatus(current, total);
start = DateTime.Now;
【讨论】:
对于循环中的相对时间测量,最好使用Stopwatch
甚至DateTime.UtcNow
,它们都比DateTime.Now
快得多。
好点。我也没有意识到 DateTime.UtcNow 更快(没有时区转换)。从回答其他问题中学到一些东西总是一种享受!您还可以使用 System.Timer 来更新 UI,尤其是当工作在另一个线程上完成时。以上是关于使用后台线程时有效显示文件状态的主要内容,如果未能解决你的问题,请参考以下文章
c# Naudio 音频电平捕获和显示,仅在打开录音属性时有效
添加到 ASP.NET Core 项目中的 site.css 文件时,CSS 不起作用。但是当作为内联添加时有效