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

时间:2008-08-15 09:19:04

标签: windows multithreading events forms delegates

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

执行工作的主密封类'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包含一个字符串消息,一个进度条的max 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似乎很快更新,但进度条永远不会移动,直到批处理几乎完成了???什么给了?

6 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

@约翰

感谢您的链接。

@Will

线程池没有收获,因为我知道它只会产生一个线程。线程的使用纯粹是为了拥有响应式UI,而SQL Server正在进行读写操作。它当然不是一个短命的线程。

关于大锤你是对的。但是,事实证明我的问题出在屏幕和椅子之间。我似乎有一批不寻常的数据,其中包含许多比其他批次更多的外键记录,并恰好在这个过程的早期被选中,这意味着currentProgress在10秒内没有得到++。

@All

感谢您的所有输入,它让我思考,这让我在代码的其他地方寻找,这导致我的谦虚时刻,我再次证明错误通常是人类:)

答案 4 :(得分:-1)

您确定在此过程中UI线程是否可以自由运行?即它不是在加入或其他等待时被阻塞?这就是我的样子。

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

BackgroundWorker将使用池线程,这比创建自己的短期线程更友好。

答案 5 :(得分:-1)

  

线程池没有收获   我知道它只会产生一个   线。纯粹使用线程   在SQL中拥有响应式UI   服务器正在被读取和打击   写道。这当然不是短暂的   活着的线程。

好的,我很感激,很高兴你找到了你的bug,但是你看过BackgroundWorker了吗?它几乎完全符合您的要求,但是以标准化的方式(即没有您自己的代理)并且无需创建新线程 - 这两者都是(可能很小,但可能仍然有用)优势。