【问题标题】:Control.Invoke must be used to interact with controls created on a separate threadControl.Invoke 必须用于与在单独线程上创建的控件进行交互
【发布时间】:2014-07-07 12:47:04
【问题描述】:

下面是compact framework 3.5启动线程的方法

public ScanEntry(string scanId)
{
   InitializeComponent();
    _scanId = scanId;
    //reader = deviceFactory.Create();
    //reader.YMEvent += new ScanEventHandler(reader_Reading);
    //reader.Enable();
 }


private void CasesEntry_Load(object sender, EventArgs e)
{
      caseCounterLabel.Text = cases.Count.ToString();
      scanIdValueLabel.Text = _scanId;
}



internal void menuItemNewScan_Click(object sender, EventArgs e)
{
       System.Threading.ThreadStart threadDelegate = new System.Threading.ThreadStart(ScanEvents);
       System.Threading.Thread newThread = new System.Threading.Thread(threadDelegate);
       newThread.Start();
}

在线程上调用下面的方法

private void ScanEvents()
{

  try
  {

     //some other codes     
      if (scanIdValueLabel.InvokeRequired)
     {
          scanIdValueLabel.Invoke((Action)(() => scanIdValueLabel.Text = "value"));
      }  


     attributeNode = docEventFile.CreateNode(XmlNodeType.Element, "Attribute", string.Empty);
     XMLUtils.CreateAttribute(docEventFile, attributeNode, "name", "SCANID");
     XMLUtils.CreateAttribute(docEventFile, attributeNode, "value", scanIdValueLabel.Text);
     attributeSetNode.AppendChild(attributeNode);
     //some other codes
  }
  catch(Execption e)
  {
     Message.Show(e.Message);
  }
}

错误:

TextAlign = 'scanIdValueLabel.TextAlign' threw an exception of type 'System.NotSupportedException' 
base {System.SystemException} = {"Control.Invoke must be used to interact with controls created on a separate thread."}

排队

XMLUtils.CreateAttribute(docEventFile, attributeNode, "value", scanIdValueLabel.Text);

我在这一行收到Control.Invoke must be used to interact with controls created on a separate thread

XMLUtils.CreateAttribute(docEventFile, attributeNode, "value", scanIdValueLabel.Text);

我已经用谷歌搜索并尝试了该解决方案,但对我不起作用。任何人都可以帮助我这样做。

谢谢

【问题讨论】:

  • 你不能从另一个线程访问scanIdValueLabel.Text
  • Message.Show 背后是什么,它是否与表单上的控件进行交互?
  • @S.Spieker 你能解释一下清楚的吗?
  • 一般规则是,您应该并且不能从创建控件的线程之外的另一个线程访问表单属性...

标签: c# .net compact-framework


【解决方案1】:

当你在处理 Winforms、WPF、Silverlight 时,下面这句话非常重要:

UI 元素只能由 UI 线程访问。 WinForms、WPF、Silverlight 不允许从多个线程访问控件。

但是,有一个解决方案可以找到here

更新:我创建了一个示例应用程序来说明一些事情:

我首先创建了一个带有按钮和标签的表单。标签不可见,因为它不包含文本,但它就在按钮下方。

场景 1:无线程更新:

private void btnStartThread_Click(object sender, EventArgs e)
{
    lblMessage.Text = "Button has been clicked.";
}

当然,这不是问题。这是一些标准代码:

场景 2:使用线程更新:

private void btnStartThread_Click(object sender, EventArgs e)
{
    System.Threading.ThreadStart threadDelegate = new System.Threading.ThreadStart(ScanEvents);
    System.Threading.Thread newThread = new System.Threading.Thread(threadDelegate);
    newThread.Start();
}

private void ScanEvents()
{
    lblMessage.Text = "Exected in another thread.";
}

这将失败,因为我正在从另一个线程修改表单上的控件:

现在,我将修改代码,以便通过对标签的调用通过操作更改标签。

private void ScanEvents()
{
    if (lblMessage.InvokeRequired)
    {
        lblMessage.Invoke((Action)(() => lblMessage.Text = "This text was placed from within a thread."));
    }
}

这将使文本发生变化。

所以,我希望它有所帮助。如果没有,请大喊:-)

【讨论】:

  • 如果您认为这是重复的,您应该将其标记为这样,而不是简单地链接到现有问题。
  • 完成。抱歉,我不知道。
  • @Complexity 您可以从后台线程访问 UI 元素,只要您不尝试修改它们的任何属性。只读是允许的。
  • 感谢您指出这一点,但查看原始问题,不清楚是否修改了其中一个属性。
  • @Complexity 你能告诉我如何在我的应用程序中使用 InvokeRequired。因为我给出的代码是用于创建 xml 属性,我在 ScanEvents 方法的第 4 行上方添加了 InvokeRequired。我仍然遇到您在回答中提到的相同异常。我想将 InvokeRequired 添加到我将输入传递给文本框控件的位置。请澄清
猜你喜欢
  • 2011-12-13
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多