簡體   English   中英

將Backgroundworker與計時器配合使用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM