c#threads并且无法调用invoke

问题描述 投票:1回答:2

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

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

但是知道我收到一个名为“无法在控件上调用Invoke或BeginInvoke,直到创建了窗口句柄”的错误。我已经搜索了解决方案,但我没有找到解决这个问题的方法。预先感谢您的帮助!

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

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();
    }
c# multithreading invoke
2个回答
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();
}

2
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.