我正在开发一个程序,该程序使用backgroundWorker
将文本附加到Textbox
控件。我的问题是,backgroundWorker
不会在Textbox
控件中插入文字,它只是空白。
我的代码:
private void button1_Click(object sender, EventArgs e) {
backgroundWorker1.RunWorkerAsync(); //Start the worker
}
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
this.writeText("Hello World!");
}
public void writeText(string text) {
textbox1.Text = textbox1.Text + text + "\r\n";
textbox1.SelectionStart = textbox1.Text.Length;
textbox1.ScrollToCaret(); //Scroll to the end of the textbox
}
看看代码,看起来很好(对我来说)并且编译也很好,所以我可能会非常明显地丢失它。
如果有人愿意让我知道我做错了什么,我将不胜感激;)
答案 0 :(得分:2)
在订阅DoWork
事件的方法中,执行长时间运行的操作。然后,在worker方法中,您可以调用ReportProgress
来发送更新。这会导致您的UI线程触发OnProgressChanged
事件,此时您可以对UI进行更改。
或者,如果您使用的是.NET 4.5,则可以使用async / await模式在执行长时间运行的I / O绑定操作时保持UI响应。对于CPU绑定操作,BackgroundWorker
仍然合适。
与往常一样,MSDN是一个很棒的资源。来自BackgroundWorker
page:
要设置后台操作,请为其添加事件处理程序 DoWork活动。在此活动中呼叫您耗时的操作 处理程序。要启动该操作,请调用RunWorkerAsync。受到 进度更新通知,处理ProgressChanged事件。 要在操作完成时收到通知,请处理 RunWorkerCompleted事件。
您必须小心不要操纵任何用户界面对象 你的DoWork事件处理程序。而是与用户界面进行通信 通过ProgressChanged和RunWorkerCompleted事件。
答案 1 :(得分:1)
您可以在表单级别为您的表单声明委托。
public delegate void WriteLogEntryDelegate(string log_entry);
然后你可以用另一种方法包装大部分逻辑:
void WriteLogEntryCB(string log_entry)
{
if (textbox1.InvokeRequired == true)
{
var d = new WriteLogEntryDelegate(WriteLogEntryCB);
this.Invoke(d, log_entry);
}
else
{
textbox1.Text(log_entry + "\r\n");
this.textbox1.SelectionStart = this.textbox1.Text.Length;
this.textbox1.ScrollToCaret();
}
}
然后,您可以从DoWork方法中调用该函数:
public void DoWork(object sender, DoWorkEventArgs e)
{
WriteLogEntryCB("Hello World!");
}
编辑以包括Daniel Mann的建议: 另一种方法是将DoWork方法中的发送方作为BackgroundWorker进行转换,然后调用ReportProgress方法(或使用RunWorkerCompleted事件处理程序)。
void bw1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
worker.ReportProgress((1));
}
然后,您需要一个ProgressChanged事件的事件处理程序:
void bw1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//update textbox here
}
最后,您还可以使用RunWorkerCompleted事件处理程序:
void bw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//update textbox here
}
答案 2 :(得分:0)
在writeText方法中,UI应该调用与UI相关的代码
创建UI控件的线程。
答案 3 :(得分:0)
您所做的就是尝试从其他线程而不是创建元素的线程访问UI元素。
阅读更多信息here。