关于多线程:Windows窗体线程和事件-ListBox会及时更新,但是Progressbar会遇到巨大的延迟

关于多线程:Windows窗体线程和事件-ListBox会及时更新,但是Progressbar会遇到巨大的延迟

Windows Forms Threading and Events - ListBox updates promptly but progressbar experiences huge delay

我们的团队正在创建一个新的招聘工作流程系统,以取代旧的工作流程系统。我的任务是将旧数据迁移到新架构中。我决定通过创建一个小的Windows Forms项目来做到这一点,因为架构根本不同,并且直接的TSQL脚本不是一个合适的解决方案。

完成工作的主要密封类" ImportController"声明了以下委托事件:

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

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

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

ImportProgressEvent args携带字符串消息,进度条的最大int值和当前的进度int值。 Windows窗体订阅该事件:

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

并使用自己的委托以这种方式响应事件:

1
2
3
4
5
6
    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);
            }

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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示例

@约翰

感谢您的链接。

@将

线程池没有任何好处,因为我知道它只会产生一个线程。在对SQL Server进行读写操作时,使用线程纯粹是为了具有响应UI。这当然不是短暂的线程。

关于大锤,您是对的。但是,事实证明,我的问题毕竟在屏幕和椅子之间。我似乎有一个异常的数据批,其外键记录比其他批次多得多,并且恰好是在过程的早期选择的,这意味着currentProgress在10秒钟之内不会获得++信息。

@所有

感谢您的所有投入,这让我开始思考,使我得以在代码中的其他地方查找,这导致了我的谦卑,我再次证明错误通常是人为的:)


您是否有机会运行Windows Vista?我注意到在某些与工作相关的应用程序中,情况完全相同。以某种方式,进度栏"动画"时似乎会有延迟。


可能不在范围之内,但是有时对Application.DoEvents();进行操作以使gui部分响应用户输入(例如,按下状态栏对话框上的"取消"按钮)很有用。


There's no gain from threadpooling as
I know it will only ever spawn one
thread. The use of a thread is purely
to have a responsive UI while SQL
Server is being pounded with reads and
writes. It's certainly not a short
lived thread.

好的,我很感激,很高兴找到您的bug,但是您有没有看过BackgroundWorker?它几乎完全按照您的操作来做,但是是以标准化的方式(即没有您自己的委托人)并且不需要创建新的线程-两者都是(也许很小,但也许仍然有用)优点。


您确定在所有此过程中UI线程都可以自由运行吗?也就是说,它不是在Join或其他等待中处于阻塞状态吗?那就是我的样子。

使用BackgroundWorker的建议是一个很好的建议-绝对优于尝试通过大量刷新/更新调用来大刀阔斧地摆脱问题。

而且BackgroundWorker将使用池线程,这是比创建自己的短期线程更友好的行为方式。


推荐阅读

    确定java按钮响应事件的代码

    确定java按钮响应事件的代码,,* 阅读本文可以结合最后在java登录窗口界面下面是一个链接。 是定义的容器。 容器(CP =得到内容面板); / /

    设置线程名称|tomcat线程名称设置

    设置线程名称|tomcat线程名称设置,,1. tomcat线程名称设置一.tomcat的优化1.tomcat的自身调优采用动静分离调优Tomcat线程池调优Tomcat的

    多线程cpu电脑|多线程的CPU

    多线程cpu电脑|多线程的CPU,,1. 多线程的CPU四核心四线程,表示这个电脑的CPU核心是4个核心、4个线程的。电脑CPU的核心数量和线程数量越多,

    90后瓶门事件图片

    90后瓶门事件图片,,现在孩子们还太早,有些女孩子总是在门口等一会儿,最近发生了一次酒瓶门事件。 近日,山东一家寄宿学校的一名女生带着一瓶

    简单的线程池(三)

    简单的线程池(三),吞吐量,线程,◆ 概要本文中,作者针对 《简单的线程池(一)》 和 《简单的线程池(二)》 介绍的两个线程池分别进行了并发测试。基