Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用线程实时更新UI_C#_Multithreading_Logging - Fatal编程技术网

C# 如何使用线程实时更新UI

C# 如何使用线程实时更新UI,c#,multithreading,logging,C#,Multithreading,Logging,我正在开发一个应用程序,它将主动读取文件,并实时分析和显示该文件中的信息 我读过的每一篇文章都告诉我应该使用某种线程来实现这一点。我研究了后台工作人员,还尝试在运行时创建一个单独的线程,并使用该线程更新所有UI元素 当我不能(或不应该)进行跨线程调用时,问题就出现了,因为原始UI元素是在不同的线程上创建的 有没有办法在将要更新这些UI元素的线程上创建这些UI元素?最好的方法是什么 编辑:这篇文章的回复(现在已经不存在了)解释了我应该怎么做。使用所述方法更新代码后 这是我使用过的更新代码。在我添加

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

我读过的每一篇文章都告诉我应该使用某种线程来实现这一点。我研究了后台工作人员,还尝试在运行时创建一个单独的线程,并使用该线程更新所有UI元素

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

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

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

会话是我创建的一个类,它通过日志文件进行解析

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);
}
private Session s1=新会话(“”);
私有文件系统监视程序fsw;
私有OpenFileDialog ofd1=新建OpenFileDialog();
私人后台工作人员bgw;
private bool logActive=false;
公共财政收入()
{
初始化组件();
bgw=新的BackgroundWorker();
bgw.WorkerReportsProgress=true;
bgw.ProgressChanged+=HandleProgressChanged;
bgw.DoWork+=手工作业;
fsw=newfilesystemwatcher(@“H:\Logs”,“*.txt”);
fsw.synchroningobject=此;
fsw.IncludeSubdirectories=false;
fsw.EnableRaisingEvents=true;
fsw.NotifyFilter=NotifyFilters.Size;
fsw.Changed+=新文件系统EventHandler(fsw_OnChanged);
}
私有void frmMain_加载(对象发送方,事件参数e)
{
ofd1.Filter=“日志文件(*.txt)|*.txt |所有文件(*.*)|*.”;
ofd1.FilterIndex=2;
ofd1.RestoreDirectory=true;
}
私有void fsw_OnChanged(对象源,System.IO.FileSystemEventArgs e)
{
bgw.RunWorkerAsync();
}
//这在UI线程上运行
//在这里,您可以根据事件参数中的信息更新UI
私有void HandleProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
对于(int i=s1.previousLineNumber;i
为了更新UI,您应该使用Invoke或BeginInvoke

void LengthyProcessInThread()
{
   ...
   foreach(var item in file)
   {
       Invoke(delegate() {
          .. Update UI here.
       });
   }
}
Invoke是控件上的一个方法,例如,包含UI的表单


祝您在任务中好运。

最好的方法是使用代理访问主线程控制。这很简单,并在stackoverflow上进行了多次描述。搜索一点,我相信你会找到有用的答案。你的方法有一个基本缺陷:你从其他线程操作UI,并在“前台”线程中执行实际工作/逻辑(例如数据分析)。然而,大多数UI框架要求的恰恰相反:在后台线程中工作,并从一个前台线程(“UI线程”)更新UI。不幸的是,这已经超出了我的直接知识范围,但我可以告诉您解决方案的一般方向:使用众多线程池库中的一个,为文件系统的每次更改启动任务。这些线程将基于文件信息构建一个数据结构,然后通过延续将数据返回到UI线程,然后UI线程可以填充控件。我只需要添加
fsw.SynchronizingObject=this
以便filesystemwatcher使用与主窗体相同的线程。