2012-01-06 3 views
0

Possible Duplicate:
Cross-thread operation not validошибки при использовании нити

У меня есть проблема с использованием многопоточности в моем приложении ниже приведены две простых методов и эти два метода называются по нажатию кнопки.
Я хочу сначала запустить метод вставки и спящий поток в течение 5 секунд после запуска 5 секунд второго режима и отображения в соответствии с кодировкой.
Но я сталкиваюсь эта ошибка:

Cross-thread operation not valid: Control 'lblDisplay' accessed from a thread other than the thread it was created on.

Вот код:

private void button1_Click(object sender, EventArgs e) 

    { 

     Thread obj = new Thread(new ThreadStart(inserting)); 

     Thread obj1 = new Thread(new ThreadStart(insert)); 

     obj.Start(); 

     obj1.Start(); 

    } 

public void inserting() 
    { 
     lblDisplay.Text = "inserting record......"; 
     Thread.Sleep(5000); 
    } 
    public void insert() 
    { 
     lblDisplay.Text = "Record successfully inserted"; 
    } 
+0

Я предлагаю вам прочитать [электронную книгу Джо Альбахари] (http://www.albahari.com/threading/) –

+2

Уже есть сотни вопросов о том, что касается точно такой же проблемы. –

ответ

1

Вы получаете сообщение об ошибке, потому что не можете получить доступ к элементам пользовательского интерфейса в потоках, отличных от основного потока пользовательского интерфейса (или поток диспетчера в WPF). Если вы хотите иметь некоторую систему обновления статуса, вам будет лучше, если процессы будут выполняться в отдельном потоке, а затем перезвоните в основной поток пользовательского интерфейса, чтобы обновить текст состояния. Например:

public void button1_Click(object sender, EventArgs e) 
{ 
    var thread = new Thread(new ThreadStart(Execute)); 
    thread.Start(); 
} 

private void Execute() 
{ 
    UpdateStatus("Starting execution..."); 

    // ... Run some code ... 

    UpdateStatus("Inserting record..."); 

    // Sleep for 5 seconds 
    Thread.Sleep(5000); 

    // ... Run record insertion code ... 

    UpdateStatus("Record successfully inserted"); 
} 

private void UpdateStatus(string status) 
{ 
    // Make sure we're running on the UI thread 
    if (this.InvokeRequired) 
    { 
     BeginInvoke(new Action<string>(UpdateStatus), status); 
     return; 
    } 

    // Update the display text now we are running on the UI thread 
    lblDisplay.Text = status; 
} 

Примечание: Это ответ, специфичный для WinForms. Для WPF вы используете CheckAccess() вместо InvokeRequired и this.Dispatcher.BeginInvoke(...) вместо BeginInvoke(...).

2

Вы можете только modifiy управление на тот же поток, как вы их создали. Используйте Control.Invoke изменить свой контроль:

lblDisplay.Invoke(() => 
{ 
    lblDisplay.Text = "inserting record......"; 
}); 
0

lblDisplay был создан в другом потоке, так что вам нужен делегат, чтобы изменить значение. Посмотрите на MSDN с примером того, что делать.

0

Я также столкнулся с этой проблемой. Я разместил решение here.

Это происходит потому, что вы пытаетесь изменить UI Control, потоком, который не создал элемент управления.

Создать расширение, как этого

public static class ControlExtensions 
{ 
    public static void Invoke(this Control control, Action action) 
    { 
     if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null); 
     else action.Invoke(); 
    } 
} 

, а затем сделать это

lblDisplay.Invoke(() => { lblDisplay.Text = "Record successfully inserted"; }); 

Надеется, что это помогает вам.

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