[英]Can not assign value for textbox in backgroundworker (c# winform)
public class Form1
{
public delegate void SetStatus (string status);
public event SetStatus SetStatusHandler;
public BackgroundWorker bw = new BackgroundWorker();
public Form1()
{
tbxResult.Text = "Assign text Ok";
SetStatusHandler += delegate(string status)
{
tbxResult.Text = status; // can not assign
};
bw.DoWork += backgroundWorker_DoWork;
bw.RunWorkerAsync();
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
var status = "assign some value";
SetStatusHandler(status);
}
}
首先,我尝试在BackgroundWorker内的主线程上设置文本框tbxResult的值,但是它不起作用,然后我使用委托从主线程分配文本框值,但它也无法正常工作...
请帮我...怎么了?
希望逻辑有道理。 但是委托声明是错误的,您必须在SetStatus
声明中指定返回类型以使其起作用。 因此,如下更改声明:
public delegate void SetStatus (string status);
仍然会收到异常(注释中提到的IllegalCrossThreadCallException
为René Vogt
)意味着您可以定义事件处理程序,如下所示:
SetStatusHandler += delegate(string status)
{
tbxResult.Invoke(new MethodInvoker(delegate
{
tbxResult.Text = status;
}));
};
我们需要使用主UI线程再次调用该方法。 看看更多信息C#中MethodInvoker的用法
tbxResult.Invoke((MethodInvoker) delegate
{
tbxResult.Text = status;
});
总的来说,我认为BackgroundWorker
已过时,最好使用async/await
模式。 但这将是一个过于宽泛的答案。
因此,直接的答案是:您的事件处理程序不在UI线程上执行,但仍在后台工作线程上执行。 从后台工作程序重新调用ui线程上的操作的通常方法是使用它的ReportProgress
方法:
public Form1()
{
tbxResult.Text = "Assign text Ok";
bw.DoWork += backgroundWorker_DoWork;
bw.WorkerReportsProgress = true;
bw.ProgressChanged += (sender, e) => tbxResult.Text = (string)e.UserState;
bw.RunWorkerAsync();
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
var status = "assign some value";
bw.ReportProgress(0, status);
}
ReportProgress()
在UI线程上调用ProgressChanged
事件,因此您可以将文本分配给文本框。 记住将WorkerReportsProgress
设置为true
。
像这样使用InvokeRequred(或与您的代表一起使用):
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (textBox1.InvokeRequired)
{
textBox1.Invoke((MethodInvoker) delegate { textBox1.Text = @"AAAAAA"; });
}
else
{
textBox1.Text = @"AAAAAA";
}
}
ps:另请参阅Invoke调用中的匿名方法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.