[英]Using Backgroundworker with a Timer
我已經在很多地方尋找了這個,但是仍然沒有找到解決方案。 我要實現的目標是能夠定時使用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
方法使rewriteOnlineStatus
方法不會火,因為它運行下去。 還有其他解決方法嗎?
我建議您使用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線程報告。
這應該是評論,而不是答案,但是我沒有足夠的聲譽積分可以發表評論。 (這個限制讓我很困惑。)
@blorgbeard的答案是正確的,但是此問題的真正重要部分是如何在后台線程中模擬計時器,而不會意外退出線程。
他實際上根本不在工作線程中使用計時器。 畢竟,將使用計時器在間隔后喚醒線程並對其進行控制。 由於線程已經具有控制權,所以竅門就是在相等的時間間隔內放棄該控制權。 他使用Sleep,然后使用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功能,但是無論如何,我在調整睡眠間隔時還有其他編碼注意事項。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.