我正在尝试使用后台工作程序来更新C#窗体中用于状态窗口的列表框。从MyForm类之外的另一个类调用addToStausLog()方法时,即使我将表单的实例传递给另一个调用addToStatusLog更新成员的类,它也似乎无法正常工作。相反,直到类成员完成并返回MyForm类后,更新才会发生。也许有更好的方法来创建实时状态窗口,该窗口将在MyForm传递给它的任何类中运行。我是工作者线程的新手,所以有人可以回顾一下,让我知道我做错了什么或可以改进。
public MyForm()
{
InitializeComponent();
// Setup background task to update listbox status so UI is unaffected
_lListBoxQue = new List<string>();
bw_listBoxBGWorker = new BackgroundWorker();
bw_listBoxBGWorker.DoWork += (o, args) => LstbxThread_doWork();
bw_listBoxBGWorker.RunWorkerCompleted += (o, args) => LstbxThread_completed();
}
private void LstbxThread_doWork()
{
System.Threading.Thread.Sleep(100);
}
private void LstbxThread_completed()
{
// Update listbox
lstStatusBox.BeginUpdate();
lstStatusBox.Items.Clear(); // clear entries
lstStatusBox.Items.AddRange(_lListBoxQue.ToArray());
lstStatusBox.EndUpdate();
}
public String addToStatusLog(String sMsg)
{
_lListBoxQue.Add(sMsg);
if (_lListBoxQue.Count > _iStatusLogMaxLines) // > max?
_lListBoxQue.RemoveAt(0); // remove top element?
if( !bw_listBoxBGWorker.IsBusy ) // background not busy?
bw_listBoxBGWorker.RunWorkerAsync(); // update listbox in back ground task
System.Threading.Thread.Sleep(100);
return sMsg;
}
这是调用另一个类的成员,该类在此过程中尝试多次调用addToStatusLog,但是直到MyClass(this).updateDB()完成后才对列表框进行更新。我需要在updateDB()函数运行时查看实时更新。我希望有一种方法可以完成这项工作,
private void btnUpdateDB_Click(object sender, EventArgs e)
{
if (_bIsUpdateEventRunning == false ) // is event not busy?
{
_bIsUpdateEventRunning = true;
new MyClass(this).updateDB();
_bIsUpdateEventRunning = false;
}
}
被称为更新表单列表框的类的示例。
Public class MyClass{
private MyForm _pForm;
public MyClass(MyForm pForm){ _pForm= pForm; }
public void updateDB(){
_pForm.addToStatusLog("Hello World");
}
}
没有后台工作程序的更新修复程序
: public String addToStatusLog(String sMsg)
{
_lListBoxQue.Add(sMsg);
if (_lListBoxQue.Count > _iStatusLogMaxLines) // > max?
_lListBoxQue.RemoveAt(0); // remove top element?
lstStatusBox.BeginUpdate();
lstStatusBox.Items.Clear(); // clear entries
lstStatusBox.Items.AddRange(_lListBoxQue.ToArray());
lstStatusBox.EndUpdate();
Application.DoEvents();
return sMsg;
}
答案 0 :(得分:0)
Thread.Sleep
在这里不是答案。您可能需要的是Application.DoEvents
。这将处理Windows消息队列中当前正在等待的所有消息。
Thread.Sleep
只是告诉线程进入睡眠状态(指定的毫秒数)。如果您的后台工作程序正在UI线程上运行,那么您正在使UI线程进入睡眠状态,这实际上是昏昏欲睡的。 (重要:所有Windows窗体都在UI线程上运行。)
当然,还有一些替代设计,其中涉及旋转单独的执行线程。但是这些都有其自身的问题,在盲目地走这条路之前,您应该注意它们。