简体   繁体   English

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

[英]Control.Invoke must be used to interact with controls created on a separate thread

Below is the method to start a thread in compact framework 3.5 下面是在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();
}

which calls the below method on thread 在线程上调用以下方法

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);
  }
}

Errors: 错误:

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."}

In Line 排队

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

I am getting Control.Invoke must be used to interact with controls created on a separate thread at this line 我正在获取Control.Invoke must be used to interact with controls created on a separate thread在此行在Control.Invoke must be used to interact with controls created on a separate threadControl.Invoke must be used to interact with controls created on a separate thread

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

I have googled and tried with that solutions but not worked for me.Can any one help me in doing this. 我已经用谷歌搜索并尝试了该解决方案,但对我没有用。任何人都可以帮助我做到这一点。

Thanks 谢谢

When you're dealing with Winforms, WPF, Silverlight there's the following sentence which is very important: 当您处理Winforms,WPF,Silverlight时,以下句子非常重要:

The UI elements can only be accessed by the UI thread. UI元素只能由UI线程访问。 WinForms, WPF, Silverlight doesn't allow access to controls from multiple threads. WinForms,WPF,Silverlight不允许从多个线程访问控件。

However, there is a solution which can be found here : 但是,它可以找到一个解决方案在这里

Update: I've created a sample application to make some things clear: 更新:我创建了一个示例应用程序来使一些事情变得清晰:

在此处输入图片说明

I've created a form first with a button and a label on it. 我首先创建了一个带有按钮和标签的表单。 The label is not visible because it doesn't contain text, but it's right underneath the button. 标签不可见,因为它不包含文本,但是在按钮下方。

Scenario 1: Updating without threads: 方案1:无线程更新:

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

Off course this is not a problem. 当然,这不是问题。 It's some standard code: 这是一些标准代码:

Scenario 2: Updating with threads: 方案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.";
}

This will fail because I'm MODIFYING the controls on my form from another thread: 这将失败,因为我正在从另一个线程修改表单上的控件:

在此处输入图片说明

Now, I will modify the code so that I'm changing the label with an action through an invoke on the label. 现在,我将修改代码,以便通过对标签的调用通过操作来更改标签。

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

This will make the text change. 这将使文本更改。

在此处输入图片说明

So, I hope that it helps. 因此,我希望这会有所帮助。 If not, please shout :-) 如果没有,请大喊:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM