如何使用线程实时更新UI

本文关键字:UI 实时更新 线程 何使用 | 更新日期: 2023-09-27 18:02:14

我正在开发一个应用程序,该应用程序将主动从文件中读取,并实时分析和显示该文件中的信息到UI。

我读过的所有东西都告诉我,我应该使用某种线程来做这件事。我探索了后台工作者,也尝试在运行时创建一个单独的线程,并使用该线程更新所有的UI元素。

当我不能(或不应该)进行跨线程调用时,问题就出现了,因为原始UI元素是在不同的线程上创建的。

是否有办法在线程上创建这些UI元素,将更新它们?最好的方法是什么?

编辑:这篇文章有一个回复(现在已经消失了),解释我应该怎么做。在用所描述的方法更新我的代码之后这是我使用的更新后的代码。一切都很好,直到我添加了文件系统监视器。一旦我添加,我得到相同的错误关于不进行跨线程调用。

Session是我创建的一个类,用于解析日志文件

private Session s1 = new Session("");
private FileSystemWatcher fsw;
private OpenFileDialog ofd1 = new OpenFileDialog();
private BackgroundWorker bgw;
private bool logActive = false;
public frmMain()
{
    InitializeComponent();
    bgw = new BackgroundWorker();
    bgw.WorkerReportsProgress = true;
    bgw.ProgressChanged += HandleProgressChanged;
    bgw.DoWork += HandleDoWork;
    fsw = new FileSystemWatcher(@"H:'Logs", "*.txt");
    fsw.SynchronizingObject = this;
    fsw.IncludeSubdirectories = false;
    fsw.EnableRaisingEvents = true;
    fsw.NotifyFilter = NotifyFilters.Size;
    fsw.Changed += new FileSystemEventHandler(fsw_OnChanged);
}
private void frmMain_Load(object sender, EventArgs e)
{
    ofd1.Filter = "log files (*.txt)|*.txt|All files (*.*)|*.*";
    ofd1.FilterIndex = 2;
    ofd1.RestoreDirectory = true;
}
private void fsw_OnChanged(object source, System.IO.FileSystemEventArgs e)
{
    bgw.RunWorkerAsync();
}
// this runs on the UI thread
// here's where you update the UI based on the information from the event args
private void HandleProgressChanged(object sender, ProgressChangedEventArgs e)
{
    for (int i = s1.previousLineNumber; i < s1.GetMessageCount(); i++)
    {
        ListViewItem lvi = new ListViewItem((s1.GetMessage(i).date).ToString());
        lvi.SubItems.Add(s1.GetMessage(i).type.ToString());
        lvi.SubItems.Add(s1.GetMessage(i).data);
        listView1.Items.Add(lvi);
    }
}
// this runs on a background thread; you cannot modify UI controls here
private void HandleDoWork(object sender, DoWorkEventArgs e)
{
    s1.ParseLiveFile();
    bgw.ReportProgress(100);
}

如何使用线程实时更新UI

为了更新UI,你应该使用Invoke或BeginInvoke。

void LengthyProcessInThread()
{
   ...
   foreach(var item in file)
   {
       Invoke(delegate() {
          .. Update UI here.
       });
   }
}

Invoke是控件上的方法,例如:包含UI的表单

祝你好运。