我需要在每个循环中从我的backgroundworker返回多个STRING值,所以我尝试使用ReportProgress第二个参数作为字符串数组。代码示例:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string[] workerResult = new string[2];
for (int i=0; i<someNumber; i++)
{
//do some heavy calculating
workerResult[0] = "this string";
workerResult[1] = "some other string";
backgroundWorker1.ReportProgress(i, workerResult) // also tried workerResult[] and [2]
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string[] results = (string[])e.UserState;
MessageBox.Show(results[0]); // line of error
MessageBox.Show(results[1]); // line of error
}
它编译,但在运行时我尝试访问Userstate返回的字符串,我收到一个错误:“对象引用未设置为对象的实例。”
对我来说,似乎在将数组参数传递给ProgressChanged委托时出错,或者在尝试设置结果数组值时在ProgressChanged方法中出错。
答案 0 :(得分:18)
您的代码段无法重现问题。标准错误是调用ReportProgress()然后继续修改对象。事件处理程序运行需要一段时间,它将看到修改后的对象,而不是原始对象。您可以通过简单地创建一个新对象来避免这种情况,以便事件处理程序始终使用原始对象。像这样:
//do some heavy calculating
for (int i = 0; i < 2; ++i) {
string[] workerResult = new string[2];
workerResult[0] = "this string";
workerResult[1] = "some other string";
backgroundWorker1.ReportProgress(i, workerResult);
}
注意如何在循环内移动数组创建语句。
答案 1 :(得分:7)
当您实例化BackgroundWorker时,您必须将reportprogress设置为true:
worker = new BackgroundWorker { WorkerReportsProgress = true };
在do work方法上你只需要这个:
worker.ReportProgress(10, "Message");
然后这样的事情来抓住进展:
private void WorkerProgressChanged(object sender, ProgressChangedEventArgs e) {
if (e.UserState != null) {
MessageBox.Show(e.UserState);
}
}
答案 2 :(得分:0)
我通过向后台工作程序添加一个新的ProgressChanged
事件侦听器解决了类似的问题,如果ProgressChanged
未被触发,则阻止传递到下一个循环:
bool progressed;
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
string[] workerResult = new string[2];
for (int i = 0; i < 2; ++i) {
progressed=true;
workerResult[0] = "this string";
workerResult[1] = "some other string";
backgroundWorker1.ReportProgress(i, workerResult);
while (progressed)
{
//you can add a thread sleep
}
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressed = false;
}