我已经在很多地方看过这个但仍未找到解决方案。我想要实现的是能够在定时的基础上使用BackgroundWorker。这是一个例子:
public Main()
{
isDbAvail = new BackgroundWorker();
isDbAvail.DoWork += isOnline;
isDbAvail.RunWorkerCompleted += rewriteOnlineStatus;
}
private void rewriteOnlineStatus(object sender, RunWorkerCompletedEventArgs e)
{
Subs.Connection connection = new Subs.Connection();
changeStatus(connection.isDbAvail());
}
private void isOnline(object sender, DoWorkEventArgs e)
{
while (true)
{
Console.WriteLine("Checking database connection");
System.Threading.Thread.Sleep(8000);
}
}
public void changeStatus(bool status)
{
if (status)
{
serverStatusVal.Text = "Connected";
serverStatusVal.ForeColor = System.Drawing.Color.DarkGreen;
}
else
{
serverStatusVal.Text = "Not connected";
serverStatusVal.ForeColor = System.Drawing.Color.Red;
}
}
这里发生的是isOnline
方法每8秒检查一次与数据库的连接(只是一个例子)并相应地更改文本。我注意到的是,isOnline
方法中的while循环导致rewriteOnlineStatus
方法永远不会触发,因为它无限期地运行。还有另一种解决方法吗?
答案 0 :(得分:2)
我建议您使用BackgroundWorker.ReportProgress
,并检查后台线程中的连接。
这样的事情:
public Main()
{
isDbAvail = new BackgroundWorker();
isDbAvail.WorkerReportsProgress = true;
isDbAvail.DoWork += isOnline;
isDbAvail.ProgressChanged += rewriteOnlineStatus;
isDbAvail.RunWorkerAsync();
}
private void rewriteOnlineStatus(object sender, ProgressChangedEventArgs e)
{
changeStatus((bool)e.UserState);
}
private void isOnline(object sender, DoWorkEventArgs e)
{
while (true)
{
Console.WriteLine("Checking database connection");
Subs.Connection connection = new Subs.Connection();
isDbAvail.ReportProgress(0, connection.isDbAvail);
System.Threading.Thread.Sleep(8000);
}
}
现在,BackgroundWorker正在开展工作,并通过ProgressChanged
向UI线程报告。
答案 1 :(得分:0)
这应该是评论,而不是答案,但是我没有足够的声誉积分可以发表评论。 (我对此限制感到困惑。)
@blorgbeard的回答是正确的,但是此问题的真正重要部分是如何在后台线程中模拟计时器,而不会意外退出线程。
他实际上根本不在工作线程中使用计时器。毕竟,将使用计时器在间隔后唤醒线程并对其进行控制。由于线程已经具有控制权,所以窍门就是在相等的时间间隔内放弃该控制权。他使用睡眠,然后使用while (true)
循环返回以再次执行线程的工作。
这是由他的这段代码执行的:
while (true)
{
// Perform the periodic background work
// This can update data structures used by the UI when it paints
CallMyRoutineToRefreshDataForUI();
// Optionally report to UI.
isDbAvail.ReportProgress(0, connection.isDbAvail);
// Use Sleep to give up control, rather than using a Timer to regain control
System.Threading.Thread.Sleep(8000);
}
此方法具有更大的适应性。就我而言,我可以更改在对话框中查找的信息。然后,即使睡眠计时器尚未过期,我也需要强制后台线程运行。
如果后台工作线程正在休眠并且无法检查取消标志,则取消后台工作线程将不会有任何效果。取而代之的是,我在Sleep周围放置了while循环,一次只睡眠了100毫秒。我将睡眠间隔放入一个外部变量中,而不是对其进行硬编码。当我需要强制运行线程时,我只是将间隔降低为1 ms,然后让它重新循环。 (我本来可以很好地使用BackgroundWorker的Cancel功能,但是无论如何我在调整Sleep间隔时还有其他编码方面的考虑。)