2013-02-15 2 views
17

Я использую нить, написанную в другом классе для обновления метки. Метка - это содержимое в основном классе Winform.Обновить ярлык из другого потока

Scanner scanner = new Scanner(ref lblCont); 
scanner.ListaFile = this.listFiles; 
Thread trd = new Thread(new ThreadStart(scanner.automaticScanner)); 
trd.IsBackground = true; 
trd.Start(); 
while (!trd.IsAlive) ; 
trd.Join(); 

Как вы можете видеть, я передаю ссылку метки в конструктор второго класса. Во втором классе (Scanner) я метод, называемый «automaticScanner», который должен обновить ярлык с этим кодом:

public Scanner(ref ToolStripStatusLabel _lblContatore) 
{ 
     lblCounter= _lblContatore; 
} 
Thread threadUpdateCounter = new Thread(new ThreadStart(this.UpdateCounter)); 
threadUpdateCounter.IsBackground = true; 
threadUpdateCounter.Start(); 
while (!threadUpdateCounter .IsAlive) ; 
threadUpdateCounter.Join(); 

private void AggiornaContatore() 
{ 
    this.lblCounter.Text = this.index.ToString();   
} 

Я получаю эту ошибку при обновлении метки:

Неверная операция поперечного потока: элемент управления «Основной» доступен из потока, отличного от потока, который был создан на

Я использую .net 4 с Winform C#.

Большое спасибо за ответы.

News: Проблема эта линия:

trd.Join(); 

Эта линия блокировать мой GUI и Lable не обновлять. Есть способы контролировать финишную нить и обновлять этикетку до конца? Thanks

+0

, но ... его правильно вызова нити в этом режиме? Тема trd = new Тема (новый ThreadStart (scanner.scansioneAutomatica)); trd.IsBackground = true; trd.Start(); while (! Trd.IsAlive); trd.Join(); В этом режиме графический интерфейс заблокирован! : S – Antonio

+0

Включить внутри класса код Action y; и функция для посещения таймера прошедшего события private void T_Elapsed (отправитель объекта, System.Timers.ElapsedEventArgs e) { C++; // делегат - это выражение «y =() => label1.Text = c.ToString()» label1.Invoke (y =() => label1.Text = c.ToString()); } –

ответ

41

Вы не можете обновлять пользовательский интерфейс из любого другого потока, кроме потока пользовательского интерфейса. Используйте это, чтобы обновить поток в потоке пользовательского интерфейса.

private void AggiornaContatore() 
{   
    if(this.lblCounter.InvokeRequired) 
    { 
     this.lblCounter.BeginInvoke((MethodInvoker) delegate() {this.lblCounter.Text = this.index.ToString(); ;});  
    } 
    else 
    { 
     this.lblCounter.Text = this.index.ToString(); ; 
    } 
} 

Пожалуйста, пройти через эту главу и больше от этой книги, чтобы получить четкое представление о резьбе:

http://www.albahari.com/threading/part2.aspx#_Rich_Client_Applications

+0

lblCounter не содержит определения для InvokeRequired, то же самое для BeginInvoke – Antonio

+0

У меня нет метки, но ToolStripStatusLabel – Antonio

+0

IIRC, InvokeRequired существует в каждом элементе управления, но ЗАЩИЩЕН, поэтому вы видите его только в " ваш текущий класс "(то есть: Form, UserControl) и пытается получить к нему доступ в другом классе (т. е. Label, TextBox) завершает работу – quetzalcoatl

10

Используйте MethodInvoker для обновления текста наклейки в другой теме.

private void AggiornaContatore() 
{ 
    MethodInvoker inv = delegate 
    { 
     this.lblCounter.Text = this.index.ToString(); 
    } 

this.Invoke(inv); 
} 

Вы получаете сообщение об ошибке, потому что ваш UI поток держит этикетку, и так как вы пытаетесь обновить его через другой поток, вы получаете исключение перекрестного потока.

Вы также можете увидеть: Threading in Windows Forms

+0

мой класс не интерфейс IDisposable. по этой причине this.IsDisposed не найден .. – Antonio

+0

@ Антонио, удалите чек и просто позвоните прямо – Habib

+0

в методе Aggiorna contatore моего класса Сканер метод Invoke не найден. – Antonio

Смежные вопросы