访问由另一个线程创建的对象而不每次都调用?

Posted

技术标签:

【中文标题】访问由另一个线程创建的对象而不每次都调用?【英文标题】:Access object created by another thread without invoking every time? 【发布时间】:2017-01-16 19:31:25 【问题描述】:

我有一个简单的状态标签,我在长时间运行的例程中经常更新它。该例程在计时器上,因此在另一个线程上,所以我收到Cross-thread operation not valid 错误。我在 SO 上找到了一个修复程序,如下所示:

lblQuery1Status.Invoke(new Action(delegate

    lblQuery1Status.Text = "Status: Publishing";
));

但是,我在例行程序中更新了此控件的文本 7 或 8 次。有没有更有效或更简单的方法来做到这一点?

【问题讨论】:

它有什么低效之处?如果您需要执行 7-8 次,请将其粘贴在一个名为 status 作为字符串输入的方法中。我在看你的代表,我真的不想刻薄——只是好奇你说高效时你在交流什么? 我想我想知道是否可以在新线程中调用它一次,而不是每次需要访问它时调用它。我是 .net 的新手,尤其是线程。 【参考方案1】:

如果你想“简化”语法,你总是可以使用内联 lambda 来“缩短”语法:

lblQuery1Status.Invoke(new Action(() => lblQuery1Status.Text = "Status: Publishing"));

您还可以为调用创建一个动作变量,并在需要时重新调用该动作:

Action updateStatus = () => 
    lblQuery1Status.Invoke(new Action(() => lblQuery1Status.Text = "Status: Publishing"));

然后您可以根据需要多次调用它:

updateStatus();

【讨论】:

是的,我知道 invoke 没有创建新线程,我只是希望有一种方法可以在 on 新线程后调用它并多次引用它之后(无需每次都调用) @Scott 啊,我的错。上次更新是否更接近您正在寻找的内容? 毫无疑问,Action 句柄看起来很有趣。我会研究一下。谢谢。【参考方案2】:

这是我采用的解决方案,基于@David L 的answer above。

动作定义:

Action<string> updateStatus = (s) => 
     statusLabel[qo.id].Invoke(new Action(() => statusLabel[qo.id].Text = s));

呼叫:

updateStatus("Opening Connection");

我意识到它并没有更高效,但它更简单、更干净,让我不再畏缩。

【讨论】:

【参考方案3】:

不幸的是,这是将数据从长时间运行的任务/线程获取到 UI 线程的最佳方式,编组有其开销,但除非你每秒调用数百次,否则我认为你会没事的 ?

【讨论】:

以上是关于访问由另一个线程创建的对象而不每次都调用?的主要内容,如果未能解决你的问题,请参考以下文章

使用 gdb/dbx 调试线程进程

Servlet第二篇Servlet实现线程安全及其他细节补充

Wpf中“由于其他线程拥有此对象,因此调用线程无法对其进行访问”

Wpf中“由于其他线程拥有此对象,因此调用线程无法对其进行访问”的问题

什么是 ThreadLocal 变量?

什么是 ThreadLocal 变量?