バックグラウンド スレッドから 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 サイトの他の関連記事を参照してください。