Исключение перекрестной нити - PullRequest
0 голосов
/ 18 февраля 2012

У меня какое-то время проблема

эта строка:

txtPastes.Text = (string)e.UserState;

выдает исключение перекрестного потока, и я не нашел никакого решения

txtPastes - текстовое поле

GuiUpdate - BackgroundWorker

lstAllPastes - список строк

    private void GuiUpdate_DoWork(object sender, DoWorkEventArgs e)
    {
        while (true)
        {
            while (lstAllPastes.Count == 0) ;

            for (int i = 0; i < lstAllPastes[0].Length; i++)
            {
                GuiUpdate.ReportProgress(0, lstAllPastes[0].Substring(0, i));
                Thread.Sleep(1);
            }
            lstAllPastes.RemoveAt(0);
        }
    }

    private void GuiUpdate_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        txtPastes.Text = (string)e.UserState;
    }

    private void GuiUpdate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

    }

Ответы [ 4 ]

5 голосов
/ 18 февраля 2012

Вы не можете обновить элемент управления пользовательского интерфейса из любого потока, кроме потока пользовательского интерфейса.Как правило, BackgroundWorker позаботится о корректном повышении событий ProgressChanged и RunWorkerCompleted в потоке пользовательского интерфейса.Поскольку в данном случае это не так, вы могли бы самостоятельно направить логику обновления пользовательского интерфейса в поток пользовательского интерфейса, используя метод Invoke:

txtPastes.Invoke(new Action(() => 
{ 
    // This code is executed on the UI thread.
    txtPastes.Text = (string)e.UserState; 
}));

Если вы работаете в WPF, выпотребуется вызвать Invoke на диспетчере элемента управления:

txtPastes.Dispatcher.Invoke(new Action(() => 
{ 
    txtPastes.Text = (string)e.UserState; 
}));

Обновление : Как отметили Томас Левеск и Ганс Пассант, вам следует выяснить причину, по которой ваше событие ProgressChangedне поднимается в потоке пользовательского интерфейса.Я подозреваю, что вы запускаете BackgroundWorker слишком рано в жизненном цикле инициализации приложения, что может привести к условиям гонки и, возможно, к NullReferenceException, если первое событие ProgressChanged возникнет до инициализации вашего текстового поля txtPastes.

2 голосов
/ 18 февраля 2012

Ну, это должно работать, конечно.Причина этого исключения не видна в вашем фрагменте.Важно то, где и когда запускается BackgroundWorker.Его метод RunWorkerAsync () использует свойство SynchronizationContext.Current, чтобы выяснить, какой поток должен выполнять обработчик события ProgressChanged.

Это может пойти не так, если:

  • Вы также запустили BGWрано, до вызова Application.Run ().Winforms или WPF еще не имели возможности установить свой собственный поставщик синхронизации.
  • Вы вызвали метод RunWorkerAsync () BGW в рабочем потоке.Поддерживается только маршалинг в поток пользовательского интерфейса. Цикл сообщений является важнейшим компонентом, позволяющим запускать код в другом потоке.
  • Форма, которая имеет элемент управления txtPastes, была создана в другом потоке.Когда BGW запущен в потоке пользовательского интерфейса, он все еще не соответствует потоку
  • Метод Show () формы был вызван в другом потоке.Который создает собственное окно Windows в неправильном потоке.
1 голос
/ 18 февраля 2012

Убедитесь, что вы запускаете BackgroundWorker из потока пользовательского интерфейса; если вы сделаете это, событие ProgressChanged будет вызвано в этом потоке, и исключение не произойдет.

0 голосов
/ 18 февраля 2012

Если вы хотите обновить свой GUI, например TextBox, вам следует прочитать эту статью:

Обновление GUI из другого потока

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...