C# - 在单独线程中将条目添加到列表时,列表框未更新
C# - Listbox not updated when an entry is added to the list in a seperate thread
我有一个 static class 可以将日志打印到列表框,这样我就可以全局使用它,所以我使用了在我的 cls_globalvariables static [=17] 中定义的 BindingList 的全局实例=].我在 UI 构造函数中将 BindingList 绑定到 UI 的列表框。
public static class cls_globalvariables
{
public static BindingList<string> logList = new BindingList<string>();
....
}
static class LOGS
{
public static void LOG_PRINT(string logMessage, bool isNotError)
{
string now = DateTime.Now.ToString();
try
{
if (logMessage == "") return;
if (!isNotError)
logMessage = "<<<ERROR>>>" + logMessage;
// Output to text file.
using (StreamWriter w = System.IO.File.AppendText(cls_globalvariables.systemlogpath))
{
w.WriteLine("[" + now + "][" + logMessage + "]");
w.Close();
}
// Save to memory
cls_globalvariables.logList.Add("[" + now + "][" + logMessage + "]");
}
catch (Exception)
{ }
}
}
public partial class Form1: Form
{
public Form1()
{
InitializeComponent();
listBox1.DataSource = cls_globalvariables.logList;
}
}
但是,我只在我的 backgroundworker 中调用 LOGS.LOG_PRINT,所以它在另一个线程中执行。列表框延迟更新,直到后台工作人员完成其过程。我错过了什么吗?
您不应在后台线程中更新 BindingList 实例,因为您将其绑定到主用户界面线程。用户界面控件并非设计为从创建它的线程以外的任何线程调用。
因此我建议您的后台线程使用新消息回调主线程,然后主线程将消息添加到绑定列表。
将 SynchronizationContext.Current 从主线程传递到后台线程,然后在 LOGS.LOG_PRINT 方法中,您应该使用 lambda 调用 SynchronizationContext 的 Post 方法来更新列表.像下面这样...
_syncContext.Post((_) => cls_globalvariables.logList.Add(str), null);
其中str是新构造的日志字符串。
我有一个 static class 可以将日志打印到列表框,这样我就可以全局使用它,所以我使用了在我的 cls_globalvariables static [=17] 中定义的 BindingList 的全局实例=].我在 UI 构造函数中将 BindingList 绑定到 UI 的列表框。
public static class cls_globalvariables
{
public static BindingList<string> logList = new BindingList<string>();
....
}
static class LOGS
{
public static void LOG_PRINT(string logMessage, bool isNotError)
{
string now = DateTime.Now.ToString();
try
{
if (logMessage == "") return;
if (!isNotError)
logMessage = "<<<ERROR>>>" + logMessage;
// Output to text file.
using (StreamWriter w = System.IO.File.AppendText(cls_globalvariables.systemlogpath))
{
w.WriteLine("[" + now + "][" + logMessage + "]");
w.Close();
}
// Save to memory
cls_globalvariables.logList.Add("[" + now + "][" + logMessage + "]");
}
catch (Exception)
{ }
}
}
public partial class Form1: Form
{
public Form1()
{
InitializeComponent();
listBox1.DataSource = cls_globalvariables.logList;
}
}
但是,我只在我的 backgroundworker 中调用 LOGS.LOG_PRINT,所以它在另一个线程中执行。列表框延迟更新,直到后台工作人员完成其过程。我错过了什么吗?
您不应在后台线程中更新 BindingList 实例,因为您将其绑定到主用户界面线程。用户界面控件并非设计为从创建它的线程以外的任何线程调用。
因此我建议您的后台线程使用新消息回调主线程,然后主线程将消息添加到绑定列表。
将 SynchronizationContext.Current 从主线程传递到后台线程,然后在 LOGS.LOG_PRINT 方法中,您应该使用 lambda 调用 SynchronizationContext 的 Post 方法来更新列表.像下面这样...
_syncContext.Post((_) => cls_globalvariables.logList.Add(str), null);
其中str是新构造的日志字符串。