【问题标题】:C# BeginInvoke in BackgroundWorker, get object property valueC#BeginInvoke在BackgroundWorker中,获取对象属性值
【发布时间】:2018-07-27 19:39:17
【问题描述】:

我在 WinForm 上有一个 trackbar。我正在BackgroundWorker 中执行一些操作。我正在使用 BeginInvoke 访问 UI 元素。现在我可以使用以下方法轻松设置trackbar 值:

trackbar.BeginInvoke((Action)(() => trackbar.Value = 50)).

如何在BackgroundWorker 中使用BeginInvoke 获取轨迹栏当前值?

length = trackbar.BeginInvoke((Action)(() => trackbar.Value)) 无法编译。

trackbar.BeginInvoke((Action)(() => length = trackbar.Value)) 编译但不起作用。

我们将不胜感激。

【问题讨论】:

  • 你不能一开始就传入你的trackbar值吗?使用 bw.RunWorkerAsync(trackbar.Value);然后在 DoWork 事件中保留本地副本?然后每次你需要更新 trackbar 的值时你更新本地副本然后继续使用 BeginInvoke 来更新它。
  • 不,我必须获取用户在运行时设置的轨迹栏的当前值。
  • 那是因为你一开始就启动后台工作程序,然后让它永远运行吗?理想情况下,您只会让后台工作程序在需要运行时运行。

标签: c# multithreading delegates backgroundworker trackbar


【解决方案1】:

BeginInvoke 无法做到这一点,因为它所做的是在内部发布消息(字面意思是 PostMessage)并返回而不进行处理。

您需要改用Invoke,它会发送消息、处理消息,然后才能恢复您的功能:

int length;
trackbar.Invoke((Action)(() => length = trackbar.Value));

不用说,这种紧密循环中的代码会影响您的性能。小心使用Invoke

【讨论】:

  • 不,因为您使用SendMessage 阅读它。 TrackBar 是一个 Windows 通用控件。
  • 非常感谢@Blindy,你拯救了这一天。在您关于“杀死性能”的评论中,没有Invoke 不在循环内。但是,如果我需要在循环的每次迭代中更新 progressbar 怎么办?你会建议我用什么? BeginInvoke?
  • 视情况而定,如果你用大量BeginInvoke 消息淹没你的消息队列,你也会降低性能。我的建议是使用BeginInvoke,但要限制你发送的数量——即每秒发送一个左右,并在中间丢弃任何一个。
  • 一般的经验法则是Invoke 当您需要数据输出 GUI 线程,否则BeginInvoke。并且尽可能少。并考虑如果您甚至需要输出数据,您可以通过在调用消息中推送逻辑来完成工作,并在 GUI 线程上处理它——如果您无法避免调用,至少不要阻止您的其他线程也!
  • 如果你正在处理 100,000 件事情,不要每件事情更新一次 UI,每 1000 件事情更新一次(即大约 100 次)。您甚至可以每 2000 次(50 次)更新一次
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-24
  • 2010-10-19
  • 1970-01-01
相关资源
最近更新 更多