我有它的应用程序编写的。净3.5.它运行一个漫长的批处理过程。我想要的应用程序,以更新状况什么样的批处理过程中是这样做的。什么是最好的方式来更新用户界面?

有帮助吗?

解决方案

BackgroundWorker听起来像你想要的对象。

其他提示

快速而肮脏的方式是使用 Application.DoEvents()但这会导致处理订单事件的问题。所以不推荐

问题可能不是你必须屈服于ui线程,而是你对ui线程进行处理阻止它处理消息。您可以使用backgroundworker组件在不同的线程上执行批处理,而不会阻止UI线程。

在后台线程上运行冗长的进程。后台工作者类是一种简单的方法 - 它为发送进度更新和完成事件提供了简单的支持,为您在正确的线程上调用事件处理程序。这使代码保持简洁明了。

要显示更新,进度条或状态栏文本是两种最常用的方法。

要记住的关键是,如果你在后台线程上做事,你必须切换到UI线程,以便更新Windows控件等。

为牛肉出人们在说什么DoEvents,这里是什么的描述可能发生。

说你有一些形式的数据在它和你的长期运行的事件是其保存数据库,或产生一份报告的基础上。你开始保存或产生的报告,然后定期你叫DoEvents使屏幕保持画。

不幸的是的屏幕是不是刚刚画,它也将作出反应以用户的行动。这是因为DoEvents停止你正在做什么现在要处理所有的窗户的邮件等待处理通过你它的应用程序。这些信息包括请求重新绘制,以及任何用户打字输入,点击,等等。

因此,例如,而你是拯救数据,用户可以做的东西喜欢制作程序显示出一个模式对话框这是完全不相关的长期任务(例如帮助->有关).现在你反应的新的用户的行动 内部 已经运行,长期运行的任务。DoEvents将返回的时候所有事件都在等待的时候你称它已完成,然后你的长期运行的任务将继续下去。

如果有什么用户不能关闭的模式对话?你的长期运行的任务永远等待,直至这个对话被关闭。如果你在犯一个数据库并保持一个交易,你现在保持的交易开放的同时,用户有一个咖啡。你的交易时间和你失去了你的持续性工作,或交易没有时间出去和你的潜在的僵局的其他用户的数据库。

这里发生了什么是该应用程序。DoEvents使你的代码重入。看到了维基百科的定义 在这里,.注意一点从上的文章,用于代码重入:

  • 必须持有没有静态(或全球)非恒定的数据。
  • 必须工作只有在将数据提供给它的呼叫者。
  • 必须不依赖于锁定单独的资源。
  • 必须不叫非重入计算机程序或惯例。

这是非常不可能长期运行的代码在它的应用程序的工作只有在数据传递给该方法通过的呼叫者不举行静态数据,有没有锁,并呼吁只有其他重入的方法。

如许多人在这里说的话,DoEvents可能会导致一些非常奇怪的情况。错误也可能导致可能非常难以诊断,以及用户是不可能告诉你"哦,这可能发生,因为我点击这一不相关的按钮的话,我等着它来保存"。

使用backgroundworker组件在单独的线程中运行批处理,这样就不会影响UI线程。

我想重述我以前的评论者所说的内容:请尽可能避免使用DoEvents(),因为这几乎总是一种“黑客”形式。并导致维护噩梦。

如果您选择BackgroundWorker(我建议),如果您想调用Controls的任何方法或属性,则必须处理对UI的跨线程调用,因为这些是线程仿射的,必须是仅从他们创建的线程调用。根据需要使用Control.Invoke()和/或Control.BeginInvoke()。

如果您在后台/工作线程中运行,则可以在其中一个UI控件上调用 Control.Invoke ,以在UI线程中运行委托。

Control.Invoke 是同步的(等待委托返回)。如果您不想等待,请使用 .BeginInvoke()仅对命令进行排队。

.BeginInvoke()的返回值允许您检查方法是否已完成或等待它完成。

使用 Backgroundworker ,如果您还尝试通过处理 ProgressChanged 事件来更新GUI线程(例如,对于 ProgressBar ) ,一定要设置 WorkerReportsProgress = true ,否则报告进度的线程会在第一次尝试调用 ReportProgress 时死亡...

抛出异常,但除非启用“抛出”,否则您可能看不到它,输出将显示该线程已退出。

Application.DoEvents()或者可能在单独的线程上运行批处理?

DoEvents()正是我所寻找的,但我也投了背景工作者的答案,因为这看起来是一个很好的解决方案,我将进行更多调查。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top