【发布时间】:2013-11-19 19:57:00
【问题描述】:
我前段时间开始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();
}
【问题讨论】:
-
不要在工作线程上创建控件。你在要求痛苦。如果您必须对涉及 UI 控件的工作线程执行任何操作,请确保它很简单。你在这里所拥有的甚至都不是很接近。
标签: c# multithreading invoke