我正在开发一个应用程序,它将主动从文件中读取并实时分析和显示该文件中的信息到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);
}
答案 0 :(得分:0)
为了更新UI,您应该使用Invoke或BeginInvoke。
void LengthyProcessInThread()
{
...
foreach(var item in file)
{
Invoke(delegate() {
.. Update UI here.
});
}
}
Invoke是控件上的一个方法,例如。包含UI的表单。
我祝你好运。