【问题标题】:The calling thread cannot access this object because a different thread owns it" exception [duplicate]调用线程无法访问此对象,因为不同的线程拥有它”异常 [重复]
【发布时间】:2013-09-08 18:11:48
【问题描述】:

您好,我是第一次在线程上工作,不确定我是否正确 我收到错误消息:

调用线程无法访问此对象,因为不同的线程拥有它”异常

   private void ImportProductStatsButtonClick(object sender, EventArgs e)
    {
        // Get the currently selected manufacturer from the combo box
        var selected = comboBoxCorporation.SelectedItem;
        buttonProductStatsAndRetailerStats.Enabled = false;
        buttonSummariseRetailerStats.Enabled = false;
        buttonSummariseProductStats.Enabled = false;
       // Do we have one?
        if (selected != null)
        {
            // Extract the combo record
            var corporation = (ComboBoxCorporrationItem)selected;

            // Do we have one?
            if (corporation.Corporation != null)
            {
                // yes
                // Make this on a seperate thread so that the UI continues to work
                var thread = new Thread(MigrateProductStats);
              thread.Start(corporation.Corporation.Id); // This enables me to pick the manufacturer that we are summarizing for
             }
        }

    }

 private void MigrateProductStats(object corporationIdObj)
    {
       // after thread completion I need to Enable my buttons.
        buttonProductStatsAndRetailerStats.Enabled = true;
        buttonSummariseProductStats.Enabled = true;

    }

【问题讨论】:

标签: c# multithreading winforms


【解决方案1】:

尝试:

private void MigrateProductStats(object corporationIdObj)
{
    Invoke(new Action(() =>
    {
       // after thread completion I need to Enable my buttons.
       buttonProductStatsAndRetailerStats.Enabled = true;
       buttonSummariseProductStats.Enabled = true;
    });
}

【讨论】:

  • 谢谢它的工作。如果我需要一键运行两个线程,是否需要使用 Invoke?
  • 当从一个线程而不是创建它的线程更改控件时,您需要调用。如果您不确定是否可以使用InvokeRequired 属性,它会告诉您是否需要使用Invoke。见msdn.microsoft.com/en-us/library/…
  • @AlessandroD'Andria:即使不需要,也可以安全使用Invoke
  • 是的,只是知道什么时候必须使用Invoke
【解决方案2】:

甚至比Control.Invoke 更好的是使用BackgroundWorker 为您处理线程。它会在 UI 线程上生成进度和完成事件,以简化 UI 更新。

如果您使用的是 C# 5,您还可以使用 async 启动后台处理,并使用 await 在处理完成时进行 UI 更新。

【讨论】:

  • 更好的是 TPL (async/await)
  • @BenVoigt 如果您发布特定代码,我可以很高兴地发布答案。
  • @BenVoigt 不,await 不像 WaitHandle.WaitOne 那样工作
  • 谢谢,在我的回答中添加了它作为另一个建议,并附有关于需要更新 C# 的说明。
猜你喜欢
  • 2014-02-13
  • 2012-06-03
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
相关资源
最近更新 更多