首頁 > 後端開發 > C++ > 如何每 30 秒從後台執行緒安全地更新一次 GUI?

如何每 30 秒從後台執行緒安全地更新一次 GUI?

Linda Hamilton
發布: 2025-01-10 10:20:42
原創
375 人瀏覽過

How to Safely Update a GUI from a Background Thread Every 30 Seconds?

安全地從後台執行緒每30秒更新一次GUI

本文探討如何在應用程式中安全地使用線程,避免錯誤,實現每30秒從後台線程更新GUI的需求。

使用者最初嘗試使用BackgroundWorker並在while循環中運行它,但由於後台工作執行緒不是STA執行緒而導致異常。

正確的做法是將資料庫呼叫與GUI更新分開。資料庫呼叫應在後台執行緒(使用BackgroundWorker)中執行。呼叫完成後,觸發進度事件通知主執行緒更新GUI。

使用者提供的程式碼展示了這個方法:

<code class="language-C#">public class UpdateController
{
    private UserController _userController;
    private BackgroundWorker _backgroundWorker;

    // ...

    public void Update()
    {
        _backgroundWorker.RunWorkerAsync();
    }

    void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // UI 更新
        _userController.UpdateUsersOnMap();
        Update(); // 此处存在潜在问题,递归调用可能导致堆栈溢出
    }

    public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        // 大型数据库任务
    }
}</code>
登入後複製

然而,使用者面臨另一個挑戰:如何每30秒觸發一次更新。在RunWorkerCompleted事件處理程序中加入10秒的休眠不可行,因為它會凍結GUI。

為了解決這個問題,可以使用一個Timer定期呼叫Update方法,該方法依序啟動資料庫呼叫和隨後的GUI更新。 更佳方案是避免在RunWorkerCompleted中遞歸呼叫Update(),而是使用System.Timers.TimerSystem.Windows.Forms.Timer來控制更新頻率。 這將確保GUI保持回應,並避免潛在的堆疊溢位錯誤。

建議的改進程式碼結構如下 (使用 System.Timers.Timer):

<code class="language-C#">public class UpdateController
{
    private UserController _userController;
    private BackgroundWorker _backgroundWorker;
    private System.Timers.Timer _timer;

    public UpdateController()
    {
        _backgroundWorker = new BackgroundWorker();
        _backgroundWorker.DoWork += backgroundWorker_DoWork;
        _backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;

        _timer = new System.Timers.Timer(30000); // 30秒
        _timer.Elapsed += Timer_Elapsed;
        _timer.AutoReset = true;
    }

    public void Start()
    {
        _timer.Start();
    }

    private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        _backgroundWorker.RunWorkerAsync();
    }

    void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // UI 更新,确保在UI线程执行
        _userController.BeginInvoke(new Action(() => _userController.UpdateUsersOnMap()));
    }

    public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        // 大型数据库任务
    }
}</code>
登入後複製

這個改進的程式碼利用Timer來控制更新頻率,避免了遞歸呼叫帶來的風險,並使用BeginInvoke確保UI更新在UI執行緒上執行,從而確保GUI的響應性。 記得在適當的時候呼叫 _timer.Stop() 來停止定時器。

以上是如何每 30 秒從後台執行緒安全地更新一次 GUI?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板