C#中“跨线程操作错误”所需的帮助

时间:2009-03-03 14:43:25

标签: c# .net multithreading debugging

在下面的代码MessageReceivedlabel1位于不同的主题上,当尝试访问它时,我会收到此错误:

  

跨线程操作无效:   从a访问控制'label1'   线程以外的线程   创建于。

foo.MessageReceived += new Agent.MessageReceivedHandler(foo_MessageReceived); 

void foo_MessageReceived(Message message)
{
   label1.Text = message.Body;
}    

我该如何解决这个问题?

更多:显然我需要使用delegateinvoke,但我不知道如何,您能否详细解释一下?

6 个答案:

答案 0 :(得分:4)

希望这将完全复制,但如果不是:

请勿从非GUI线程触摸GUI。使用BackgroundWorker并适当地报告进度,或者阅读the WinForms page of my threading article以获得更直接的控制(Control.Invoke / BeginInvoke)。

答案 1 :(得分:1)

委托将标签更新到创建标签的线程,而不是直接尝试更新标签。

答案 2 :(得分:1)

您需要使用Control.Invoke(或Control.BeginInvoke)。首先,创建一个新的Windows窗体应用程序并添加标签和按钮。双击Visual Studio中的按钮编辑它的Click事件并添加以下代码:

    private void button1_Click(object sender, EventArgs e)
    {
        new System.Threading.Thread(new System.Threading.ThreadStart(Run)).Start();
    }

    void Run()
    {
        label1.Invoke(new Action(delegate()
        {
            label1.Text = System.Threading.Thread.CurrentThread.Name + " " + System.DateTime.Now.ToString();
        }));
    }

答案 3 :(得分:0)

这完全没有帮助。我希望自己可以投票。

我可能已经过时了,但从我记得的情况来看,除了主线之外,你不允许在GUI中改变任何东西。

答案 4 :(得分:0)

在您的Agent类中,当您引发MessageReceived事件时,您必须检查事件处理程序的Target是否实现了ISynchronizeInvoke。 如果是,并且InvokeRequired属性返回true,则必须调用eventhandler。

如果您不使用WinForms,而是使用WPF,则不能再依赖ISynchronizeInvoke,因为WPF控件不实现该接口。 相反,您必须使用AsyncOperation和AsyncOperatoinManager。

答案 5 :(得分:0)

始终确保在主线程(GUI线程)上更新GUI。

foo.MessageReceived + = new Agent.MessageReceivedHandler(foo_MessageReceived);

public delegate void MyDelegate(Message msg);
void foo_MessageReceived(Message message)
{ 
   if (InvokeRequired)
   {
      BeginInvoke(new MyDelegate(foo_MessageReceived),new object[]{message});
   }
   else
   {
      label1.Text = message.Body;
   }
}