必须使用Control.Invoke与在单独线程上创建的控件进行交互

时间:2014-07-07 12:47:04

标签: c# .net 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);

我用谷歌搜索并尝试了解决方案,但没有为我工作。任何人都可以帮助我这样做。

由于

1 个答案:

答案 0 :(得分:8)

当您与Winforms,WPF,Silverlight打交道时,下面的句子非常重要:

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

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

更新:我已经创建了一个示例应用程序,以便明确一些事项:

enter image description 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.";
}

这会失败,因为我修改了另一个帖子中表单上的控件:

enter image description here

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

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

这将使文本发生变化。

enter image description here

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