我有一个用.NET Winforms编写的项目。
我需要实现一个数据挖掘操作,将文本打印到TextBox并更新进度。
我试图使用BackgroundWorker来完成,但它抛出了一个InvalidOperationException(Cross-thread operation not valid: Control ‘xxxxx’ accessed from a thread other than the thread it was created on)
为了缩小问题可能的原因范围,我开始了一个新项目,并包括以下内容: Button - 启动BackgroundWorker Label - 打印文本。 和ProgressBar。
然而,结果是一样的。我在SOF上搜索,被告知要使用委托,但我不熟悉它。
这是引发错误的代码示例:
当我程序化地将文本框添加到面板控件时,错误仍然会发生。
最终,我用以下方法进行替换:
我试图使用BackgroundWorker来完成,但它抛出了一个InvalidOperationException(Cross-thread operation not valid: Control ‘xxxxx’ accessed from a thread other than the thread it was created on)
为了缩小问题可能的原因范围,我开始了一个新项目,并包括以下内容: Button - 启动BackgroundWorker Label - 打印文本。 和ProgressBar。
然而,结果是一样的。我在SOF上搜索,被告知要使用委托,但我不熟悉它。
这是引发错误的代码示例:
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace TestProject
{
public partial class Form1 : Form
{
private readonly BackgroundWorker _bw = new BackgroundWorker();
public Form1()
{
InitializeComponent();
_bw.DoWork += RosterWork;
_bw.ProgressChanged += BwProgressChanged;
_bw.RunWorkerCompleted += BwRunWorkerCompleted;
_bw.WorkerReportsProgress = true;
_bw.WorkerSupportsCancellation = false;
}
private void RosterWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
for (int i = 0; i < 1000; i++)
{
label1.Text = i.ToString();
_bw.ReportProgress(Convert.ToInt32((i * (100 / 1000))));
}
}
private void BwProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void btnStart_Click(object sender, EventArgs e)
{
progressBar1.Show();
_bw.RunWorkerAsync();
}
private void BwRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.Hide();
}
}
}
更新: 我按照Jon Skeet的答案进行了尝试,它在我的测试项目中确实有效,但是回到我的真实项目时,
我的表单布局如下:
表单 - 选项卡控件 - 选项卡1 -选项卡1面板 -文本框1
当执行到这一行时:
TextBox txtbox1 = new TextBox();
Tab1Panel.Controls.Add(txtbox1);
当我程序化地将文本框添加到面板控件时,错误仍然会发生。
最终,我用以下方法进行替换:
if (Tab1Panel.InvokeRequired)
Tab1Panel.Invoke((MethodInvoker)delegate { Tab1Panel.Controls.Add(txtbox1); });
else
Tab1Panel.Controls.Add(txtbox1);
一切都是工作。如何确定控件是否需要调用InvokeRequired?它是否指定了控件?