Rek*_*kar 6 c# parallel-processing multithreading listbox winforms
我需要一些帮助来试图弄清楚我做错了什么.我正在尝试从单独的线程中获取系统日志中的项集合,以防止表单在收集过程中被冻结.我可以让后台工作者抓住它们,但我有一些问题将它们添加到ListBox表单上.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
foreach (System.Diagnostics.EventLogEntry entry in eventLog1.Entries)
{
listBox1.Items.Add(
entry.EntryType.ToString() + " - " +
entry.TimeWritten + " - " +
entry.Source);
}
}
Run Code Online (Sandbox Code Playgroud)
显然这不会按预期工作,因为有2个单独的线程,你不能像我发现的那样更改不同线程上的对象.所以,如果有人能指导我朝着正确的方向前进,我会感激不尽.
您不应从非 UI 线程访问 UI 元素。Run ReportProgress,它将与 UI 线程同步。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
foreach (System.Diagnostics.EventLogEntry entry in eventLog1.Entries)
{
var newEntry = entry.EntryType + " - " + entry.TimeWritten + " - " + entry.Source;
backgroundWorker1.ReportProgress(0, newEntry);
}
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var newEntry = (string)e.UserState;
listBox1.Items.Add(newEntry);
}
Run Code Online (Sandbox Code Playgroud)
确保您启用WorkerReportsProgress.
backgroundWorker1.WorkerReportsProgress = true;
Run Code Online (Sandbox Code Playgroud)
并订阅了ProgressChanged
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
Run Code Online (Sandbox Code Playgroud)
Control.Invoke另一种方法是内部调用
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
foreach (System.Diagnostics.EventLogEntry entry in eventLog1.Entries)
{
var newEntry = entry.EntryType.ToString() + " - " + entry.TimeWritten + " - " + entry.Source;
Action action = () => listBox1.Items.Add(newEntry);
Invoke(action);
}
}
Run Code Online (Sandbox Code Playgroud)
但通过这种方法,您不需要BackgroundWorker使用ProgressChanged与RunWorkerCompletedUI 线程同步的事件处理程序。