Windows窗体线程和事件 – ListBox更新迅速,但进度条经历了巨大的延迟

我们的团队正在创build一个新的招聘工作stream程系统来取代旧的。 我负责将旧数据迁移到新的模式中。 我已经决定通过创build一个小的Windows窗体项目来做到这一点,因为架构是截然不同的,直接的TSQL脚本不是一个适当的解决scheme。

执行该工作的主要密封类“ImportController”声明以下委托事件

public delegate void ImportProgressEventHandler(object sender, ImportProgressEventArgs e); public static event ImportProgressEventHandler importProgressEvent; 

窗口使用新线程在该类中启动一个静态方法:

 Thread dataProcessingThread = new Thread(new ParameterizedThreadStart(ImportController.ImportData)); dataProcessingThread.Name = "Data Importer: Data Processing Thread"; dataProcessingThread.Start(settings); 

ImportProgressEvent args携带一个string消息,进度条的最大int值和当前进度int值。 Windows窗体描述事件:

 ImportController.importProgressEvent += new ImportController.ImportProgressEventHandler(ImportController_importProgressEvent); 

并以这种方式使用自己的代理来响应事件:

  private delegate void TaskCompletedUIDelegate(string completedTask, int currentProgress, int progressMax); private void ImportController_importProgressEvent(object sender, ImportProgressEventArgs e) { this.Invoke(new TaskCompletedUIDelegate(this.DisplayCompletedTask), e.CompletedTask, e.CurrentProgress, e.ProgressMax); } 

最后进度条和列表框被更新:

 private void DisplayCompletedTask(string completedTask, int currentProgress, int progressMax) { string[] items = completedTask.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in items) { this.lstTasks.Items.Add(item); } if (currentProgress >= 0 && progressMax > 0 && currentProgress <= progressMax) { this.ImportProgressBar.Maximum = progressMax; this.ImportProgressBar.Value = currentProgress; } } 

事情是ListBox似乎更新非常迅速,但进度条永远不会移动,直到批处理几乎完成无论如何? 是什么赋予了 ?

也许你可以尝试BackgroundWorker组件。 它使线程更容易。 这里的例子:

  • BackgroundWorker线程和支持取消
  • 在.NET 2应用程序中使用BackgroundWorker组件
  • BackgroundWorker示例

也许在范围之外,但有时它有用的做一个Application.DoEvents(); 使gui部分对用户输入作出反应,例如按下状态栏对话框上的取消按钮。

你有没有机会运行Windows Vista? 我注意到在一些工作相关的应用程序中完全一样的东西。 不知何故,进度条“动画”似乎有一个延迟。

@约翰

感谢您的链接。

@将

线程池没有任何收益,因为我知道它只会产生一个线程。 一个线程的使用纯粹是为了有一个响应式的用户界面,而SQL server正在读取和写入。 这当然不是一个短暂的线程。

关于大锤你是对的。 但是,事实证明我的问题毕竟是在屏幕和椅子之间。 我似乎有一个异常的一批数据,比其他批次有许多许多更多的外键记录,只是碰巧在这个过程中被选中,意味着currentProgress没有得到10分钟的++。

@所有

感谢您的所有意见,这让我思考,这让我在代码中的其他地方,这导致我谦逊的时刻,我再次证明,错误通常是人类:)

你确定UI线程在这个过程中是否自由运行? 即它不是坐在加入或其他等待? 这就是我看起来的样子。

使用BackgroundWorker的建议是一个很好的建议 – 绝对优于尝试用大量刷新/更新调用来解决问题的方法。

而BackgroundWorker将使用一个池线程,这是比创建自己的短暂线程更友好的方式。

线程池没有任何收益,因为我知道它只会产生一个线程。 一个线程的使用纯粹是为了有一个响应式的用户界面,而SQL server正在读取和写入。 这当然不是一个短暂的线程。

好的,我明白了,很高兴你找到了你的bug,但是你看过BackgroundWorker吗? 它几乎完全是你在做什么,而是以标准化的方式(即没有你自己的代表),而不需要创建一个新的线程 – 这两个都是(也许很小,但也许还是有用的)优点。