2010-08-06 48 views
2

HI,BeginInvoke的错误

这quetion是在延续我在this link问题。

我写了一个应用程序来比较在那里使用的方法和其他方法。在调试模式下运行应用程序时,出现错误“调用或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

@ 366436 ABHI你在哪里住在印度 – 2010-08-06 08:22:33

+0

史蒂芬你好,我是印度裔,但我总部设在英国目前。 – 2010-08-06 08:31:48

+1

尝试将代码从Form1构造移动到为onload事件的形式的。 (除了导致InitializeComponents-调用)。 – Alxandr 2010-08-06 08:41:03

回答

1

首先,有几件事情我说的代码的结构张贴可能的帮助。

什么代码确实是这样的:

  • 在构造为Form1,异步调用的方法(在不同的线程)
  • 这种方法异步调用四次调用一个单独的方法来更新标签控件。该所调用被推回到UI线程
  • 构造函数(我们在Form1的构造函数的线程),同时,等待原来的方法继续

之前有这许多sillinesses的完成代码:

  • 异步调用方法(以非阻塞方式),然后代码等待其完成。除非这个代码在后台线程上有一个令人信服的理由,否则为什么不只是同步地调用这个方法呢?它将使最终的行为保持不变,但使调试和阅读代码更容易。
  • 由于while循环等待ar.IsCompleted,您会发现UI线程实际上非常繁忙 - 在该空循环中敲击CPU,而不是坐在空闲位置并允许后台线程运行。我怀疑同步调用该方法会更高效。
  • 由于UpdateCustDetails使用BeginInvoke,它将发送四个异步调用并立即返回。这意味着 - 即使构造函数正在等待ar.IsCompleted - 您不能保证在构造函数完成时标签将被更新 - 因为对updateLabel的四次调用未被阻止。
  • 实际上,因为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"); 
    } 
} 

你会得到相同的结果,具有更好的性能,更可读的代码。

+0

喜丹, 我会做同样的事情,如果我写了相同的代码自己,但我想使这个代码的工作,看看会发生什么,如果可能的话,与普通常识的做法进行比较。实际上,这个代码是我们系统中的一个应用程序的一部分,我将来会维护它。 :-(请相信你我来说,应用程序充满了这样的“聪明”的代码。 能否请你告诉我如何做此代码的工作,这样我可以用各种其他方法进行比较。至少它会让我知道不该做什么以及为什么 谢谢, Abhi。 – 2010-08-06 08:58:56

+0

我能够使代码工作,我并不惊讶地发现,正常方法比BeginInvoke方法更有效。 – 2010-08-06 10:39:17