2010-08-06 2 views
2

HI,BeginInvoke ошибка

Это quetion в продолжении на мой вопрос в this link.

Я написал приложение, чтобы сравнить подход, используемый там, другими способами. При запуске приложения в режиме отладки я получил сообщение об ошибке: «Invoke или BeginInvoke не могут быть вызваны на элемент управления до тех пор, пока не будет создан дескриптор окна». на первом BeginInvoke в методе UpdateCustDetails. Хотя при запуске кода без отладки он не дает никакой ошибки во время выполнения. Есть идеи??

Thanks, 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

Hi Steven, я из индейского происхождения, но в настоящее время базируюсь в Великобритании. –

+1

Попробуйте переместить код из конструктора Form1 в onload-событие формы. (За исключением причины вызова InitializeComponents). – Alxandr

ответ

1

Во-первых, есть несколько вещей, которые я бы сказал о структуре кода отвечал, что могло бы помочь.

Что делает код это:

  • В конструкторе Form1, асинхронно вызывает метод (на другом потоке)
  • Этот метод асинхронно вызывающую четыре вызова в отдельный метод для обновления управления этикетки , В вызывающих отброшены в поток пользовательского интерфейса (нити мы были в на конструкторе Form1 в)
  • Конструктора, тем временем, ждет оригинальный метод, прежде чем продолжать

Есть целый ряд sillinesses в этом код:

  • Метод вызывается асинхронно (неблокирующим образом), а затем код ждет его завершения. Если нет убедительной причины для того, чтобы этот код находился в фоновом потоке, почему бы просто не вызвать метод синхронно? Это оставит конечное поведение одинаковым, но значительно облегчит отладку и чтение кода.
  • Из-за цикла while, ожидающего на ar.IsCompleted, вы обнаружите, что поток пользовательского интерфейса на самом деле довольно занят - забивает процессор в этом пустом цикле вместо того, чтобы сидеть без дела и разрешать фоновые потоки. Я подозреваю, что вызов метода синхронно будет более результативным.
  • Поскольку UpdateCustDetails использует BeginInvoke, он отправит четыре асинхронных вызова и немедленно их вернет. Это означает, что даже если конструктор ждет ar.IsCompleted - у вас нет гарантии, что метки будут обновляться к моменту завершения конструктора - поскольку четыре вызова updateLabel не блокируются.
  • На самом деле, поскольку Form.BeginInvoke выполняет казнь обратно в поток пользовательского интерфейса формы, то, что вы действительно делаете, это отбрасывание фонового потока, чтобы отбросить работу обратно в поток, который его создал.

Короче: игнорировать ошибку, вынимают все умные ищет вещи нить, и просто сделать это:

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

Hi Dan, Я бы сделал то же самое, если бы сам написал тот же код, но я хочу, чтобы этот код работал, и посмотрел, что он делает, и, если возможно, сравните его с обычным здравым смыслом. На самом деле этот код является частью приложения, которое у нас есть в нашей системе, и я должен поддерживать его в будущем. :-(И поверьте мне, приложение заполнено «умными» кодами вроде этого. Не могли бы вы посоветовать мне, как заставить этот код работать, чтобы я мог сравнивать его с другими другими подходами. По крайней мере, это позволит мне знаю, что не делать и почему. Спасибо, Abhi. –

+0

Мне удалось заставить код работать, и я не удивился, увидев, что нормальный подход был более эффективным, чем подход BeginInvoke. –