我在应用程序的WinForm中有一个标签,我为它创建了一个帖子 设置标签的Text属性。 因为代码负责设置的Text属性 标签是另一个线程,我这样写了:
private void SetLabel8Text(string text)
{
try
{
if (this.label8.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetLabel8Text);
this.Invoke(d, new object[] { text });
}
else
{
this.label8.Text = text;
}
}
catch (Exception ex)
{
}
}
现在,我也像这样处理KeyPress事件:
if (e.KeyChar.ToString() == "\r")
{
SetLabel8Text("Enter key Pressed !");
}
我面临的问题是按下Enter键后(执行 KeyPress事件),SetLabel8Text方法永远不会被执行。
其他一切似乎都很顺利, 我试着单步执行代码,它挂在这个地方(在SetLabe8Text方法内部:
this.Invoke(d,new object [] {text});
它挂起并且不会前进一点。
答案 0 :(得分:4)
好吧,你吞下SetLabel8Text
抛出的任何异常都会让人很难确切地知道发生了什么。你应该永远无条件地吞下异常而不至少记录正在发生的事情。 (你也不应该只捕获“异常”。捕获更具体的异常类型)。你能发一个简短但完整的程序来证明这个问题。
在按键事件和SetLabel8Text
中添加记录也会有所帮助。
答案 1 :(得分:1)
尝试拨打BeginInvoke
而不是Invoke
。
Invoke
是一个阻止通话,因此您可能会遇到竞争条件。 (Invoke
在方法实际执行之前不会返回,但只有在UI线程处理其消息循环后才能执行该方法。
答案 2 :(得分:0)
尝试以下方法:
if(e.KeyChar == '\n')
SetLabel8Text("Enter key Pressed !");
答案 3 :(得分:0)
尝试:
if (e.KeyCode == Keys.Enter) {
}
答案 4 :(得分:0)
一个可能的解释可能是你接下来要做的事情。假设在另一个线程中调用了SetLabel8Text函数,它将需要调用,从而再次执行。但是,它第二次执行(因此不需要调用)它在拥有GUI的线程中执行,通常是主线程。因此,如果你的应用程序中的其他地方有一段时间阻塞主线程的代码,那么看起来SetLabel8Text函数永远不会被执行第二次。为了简单起见,总是将繁重的任务线程化并保持主线程空闲。
答案 5 :(得分:0)
您没有遵循winforms的基本原则:仅在UI线程上创建UI控件。您的KeyPress事件的事件处理程序位于UI线程上,因此,如果您的标签是在UI线程上创建的,则不需要在其上使用BeginInvoke / Invoke。
如果你在UI线程以外的线程中创建表单,控件等,你可能做错了。
请参阅:http://weblogs.asp.net/justin_rogers/pages/126345.aspx了解血腥细节。