背景
根据我在这里收到的宝贵建议,我现在已将所有数据库密集型代码移至后台工作程序,特别是对数据库的直接调用。该代码在后台工作人员的 DoWork 事件期间执行。如果在 DoWork 事件期间返回 DataTable,我将该 DataTable 设置为类范围的变量。这样做是为了避免每次运行此代码时都必须调用需要 DataTable 的控件。
在执行该代码时,我在主 UI 线程中更新了一个标签,以让用户知道正在发生某些事情。为了更新标签,我使用了一个计时器,例如每 750 毫秒一个“。” 附加到标签的字符串中。
我注意到的第一件事是 backgroundworker 的 RunWorkerCompleted 事件没有触发。为了解决这个问题,我Application.DoEvents();
在每次打电话给后台工作人员之前都做了一个。这很丑陋,但它导致了事件的触发。如果有人有替代方法来解决这个问题,我会全力以赴。
然后我遇到了一个有趣的困境。如果我在 Visual Studio 2010 中运行程序,在调试模式下,我会收到一个 InvalidOperationException 错误,指出“跨线程操作无效:控制 'lblStatus' 从创建它的线程以外的线程访问”。在后台工作人员的 RunWorkerCompleted 事件期间发生此错误,我在主 UI 线程中设置标签的文本。但是,当我通过可执行文件直接启动应用程序时,它完全可以按预期工作(即标签的文本设置正确)。
问题
谁能解释正在发生的事情/就如何改进这一点提供建议?
代码
我不能发布所有涉及的代码,但这里有一些相关的东西:
namespace Test
{
public partial class frmMain : Form
{
public static Boolean bStatus = false;
static Boolean bTimer = false;
System.Timers.Timer MyTimer = new System.Timers.Timer();
public frmMain()
{
InitializeComponent();
MyTimer.Elapsed += new System.Timers.ElapsedEventHandler(MyTimer_Elapsed);
MyTimer.Interval = 750; // Every 3/4 of a second
ExampleTrigger();
}
/// <Insert>Lots of unshown code here</Insert>
private void ExampleTrigger()
{
// This is used to simulate an event that would require the backgroundworker
Application.DoEvents();
bgw.RunWorkerAsync(0);
WaitText("Example - 1");
}
private static void MyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
bTimer = true;
}
// Update status text
private void WaitText(string txt)
{
MyTimer.Enabled = true;
lblStatus.Text = txt;
bStatus = false;
while (!bStatus)
{
if (bTimer)
{
txt = txt + ".";
lblStatus.Text = txt;
lblStatus.Update();
bTimer = false;
}
}
MyTimer.Enabled = false;
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
int iSelect = (int)e.Argument;
switch (iSelect)
{
case 0:
// Hit the database
break;
/// <Insert>Other cases here</Insert>
default:
// Do something magical!
break;
}
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bStatus = true;
lblStatus.Text = "Ready!"; // This is where the exception occurs!
}
}
}