c#threads并且无法调用invoke

时间:2013-11-19 19:57:01

标签: c# multithreading invoke

我刚刚开始使用c#,所以有些东西与java完全不同,前几天我遇到了一个关于线程更改 UI (向DataGridView添加行)我发现我必须调用方法Invoke来实现这一点。我做了,一切正常,但现在我面临一个新问题。所以,我有一个框架,将显示一些动态添加的标签,我希望这样:

 Thread t = new Thread() {
        public void run() {
            while (true) {
                // for each label
                for (it = labels.iterator(); it.hasNext();) {
                    JLabel lb = it.next();
                    if (lb.getLocation().x + lb.getWidth() < 0) {
                            if (msgsRemover.contains(lb.getText().toString())) {
                            it.remove();
                            MyPanel.this.remove(lb);
                            msgsRemover.remove(lb.getText().toString());
                        } else {
                            // if there is no message to be removed, this will just continue
                            // going to the end of the queue
                            MyPanel.this.remove(lb);
                            MyPanel.this.add(lb);
                        }
                        MyPanel.this.repaint();
                        MyPanel.this.validate();
                    }
                    lb.setLocation(lb.getLocation().x - 3, 0);
                }
                MyPanel.this.repaint();


                try {
                    SwingUtilities.invokeAndWait(running);
                    sleep(30);
                } catch (InterruptedException ex) {
                    Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    };

但是在C#中我遇到问题:

MyPanel.this.remove(lb);
MyPanel.this.add(lb);

所以我做了:

  if (lb.Location.X + lb.Width < 0) {

     if (msgsRemover.Contains(lb.Text.ToString())) {
           labels.Remove(label);
           this.Invoke(new MethodInvoker(() => { this.Controls.Remove(lb); }));
           msgsRemover.Remove(lb.Text.ToString());
     } else {
            // if there is no message to be removed, this will just continue
            // going to the end of the queue
             this.Invoke(new MethodInvoker(() => { this.Controls.Remove(lb); }));
             this.Invoke(new MethodInvoker(() => { this.Controls.Add(lb); }));                              
              }
       this.Invoke(new MethodInvoker(() => { this.Refresh(); }));

但是我知道我收到一个名为&#34的错误;在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。&#34; 我一直在寻找解决方案,但我没有找到解决这个问题的方法。 提前感谢您的帮助!

编辑:启动线程是我在构造函数中做的最后一件事......有代码:

public MyPanel(Color corLabel, Color back, Font text){
        this.color = corLabel;
    this.backg = back;
    this.textFont = text;
    this.Width = 500000;

        texto = new LinkedList<string>();
    msgs = new LinkedList<MensagemParaEcra>();
    labels = new LinkedList<Label>();
    var it = labels.GetEnumerator();
    var it2 = msgsRemover.GetEnumerator();

    this.FlowDirection = FlowDirection.LeftToRight;
    this.BackColor = backg;
    this.Size = new Size(500000, 30);
    this.Refresh();

    startThread();
    }

2 个答案:

答案 0 :(得分:2)

您收到的错误表示目标Window尚未完全创建。可能构造函数还没有完成。尝试连接目标窗口的一个默认事件(加载,显示等),并在处理完这些事件后进行调用。

答案 1 :(得分:2)

您必须在控件创建了一个句柄后启动该线程才能执行Invoke,最简单的方法是覆盖OnHandleCreated方法并在那里启动您的线程。

public MyPanel(Color corLabel, Color back, Font text)
{
    this.color = corLabel;
    this.backg = back;
    this.textFont = text;
    this.Width = 500000;

        texto = new LinkedList<string>();
    msgs = new LinkedList<MensagemParaEcra>();
    labels = new LinkedList<Label>();
    var it = labels.GetEnumerator();
    var it2 = msgsRemover.GetEnumerator();

    this.FlowDirection = FlowDirection.LeftToRight;
    this.BackColor = backg;
    this.Size = new Size(500000, 30);
    this.Refresh();
}

protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);
    startThread();
}