我刚刚开始使用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();
}
答案 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();
}