HI,
这句话继续问我this link的问题。
我写了一个应用程序来比较那里使用的方法和其他方法。在调试模式下运行应用程序时,我收到错误“在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke”。在方法UpdateCustDetails中的第一个BeginInvoke上。虽然,它没有在没有调试的情况下运行代码时给出任何运行时错误。任何想法??
谢谢, ABHI。
以下是我的代码: -
public delegate void UpdateLabelDelegate(Label lb, string text);
public delegate void loadCustomersDelegate();
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
loadCustomersDelegate del = new loadCustomersDelegate(UpdateCustDetails);
IAsyncResult ar = del.BeginInvoke(null, null);
while (!ar.IsCompleted)
{
}
}
public void updateLabel(Label lb, string text)
{
lb.Text = text;
}
public void UpdateCustDetails()
{
BeginInvoke(new UpdateLabelDelegate(updateLabel), new object[] { label1, "Test" });
BeginInvoke(new UpdateLabelDelegate(updateLabel), new object[] { label2, "Test1234" });
BeginInvoke(new UpdateLabelDelegate(updateLabel), new object[] { label3, "Test5678" });
BeginInvoke(new UpdateLabelDelegate(updateLabel), new object[] { label4, "Test0000" });
}
}
答案 0 :(得分:1)
首先,我会就发布的代码结构提出一些可能有用的建议。
代码的作用是:
Form1
的构造函数中,异步调用方法(在不同的线程上)此代码中有许多内容:
while
循环等待ar.IsCompleted
,你会发现UI线程实际上非常繁忙 - 在那个空循环上锤击CPU,而不是闲置并允许后台线程跑。我怀疑同步调用该方法会更有效。UpdateCustDetails
使用BeginInvoke
,它将发送四个异步调用并立即返回。这意味着 - 即使构造函数正在等待ar.IsCompleted
- 您也无法保证在构造函数完成时更新标签 - 因为对updateLabel
的四次调用都没有阻塞。 / LI>
Form.BeginInvoke
将执行踢回到表单的UI线程,所以你真正要做的就是启动后台线程,只是为了将工作重新放回创建它的线程。 所以简而言之:忽略错误,取出所有聪明的线程,然后执行此操作:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
UpdateCustDetails();
}
public void updateLabel(Label lb, string text)
{
lb.Text = text;
}
public void UpdateCustDetails()
{
updateLabel(label1, "Test");
updateLabel(label2, "Test1234");
updateLabel(label3, "Test5678");
updateLabel(label4, "Test0000");
}
}
您将获得相同的结果,更好的性能和更易读的代码。