ホームページ >バックエンド開発 >C++ >バックグラウンド スレッドから 30 秒ごとに GUI を安全に更新するにはどうすればよいですか?

バックグラウンド スレッドから 30 秒ごとに GUI を安全に更新するにはどうすればよいですか?

Linda Hamilton
Linda Hamiltonオリジナル
2025-01-10 10:20:42438ブラウズ

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 がフリーズするため実現できません。

この問題を解決するには、タイマーを使用して Update メソッドを定期的に呼び出します。これにより、データベース呼び出しとその後の GUI 更新が開始されます。 より良い解決策は、RunWorkerCompleted 内で Update() を再帰的に呼び出すことを避け、代わりに System.Timers.Timer または System.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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。