使用后台线程时有效显示文件状态

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 不起作用。但是当作为内联添加时有效

Flutter 推送通知仅在应用程序处于后台时有效

Process.Start() 未启动 .exe 文件(手动运行时有效)

加载图像仅在可执行文件打开时有效

创建CCtexture时找不到Spritebuilder文件,但在创建CCsprite时有效?