Сбой делегата BackgroundWorker DoWork при использовании XmlReader

Я пытаюсь прочитать поток XML, используя BackgroundWorker:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
            NetworkStream serverStream = clientSocket.GetStream();
            XmlReader r = XmlReader.Create(serverStream);

            while (r.Read())
            {
  output something using backgroundWorker1.ReportProgress object
            }
    }

Я вызываю это, используя backgroundWorker1.RunWorkerAsync(null) в событии нажатия кнопки.

Программа компилируется и работает нормально, но процесс останавливается на XmlReader.Create. Ошибок нет, но он говорит, что не может оценить выражение, потому что собственный фрейм находится поверх стека вызовов. Так что, вероятно, ждет завершения процесса.

Проблема в том, что если я делаю это непосредственно щелчком мыши, не используя объект backgroundWorker, программа работает нормально.

Любые идеи? Спасибо.


person snaee    schedule 25.07.2011    source источник
comment
Как вы передаете clientSocket ? Вы на 100% уверены, что это то же самое и не используется вне бгв?   -  person Henk Holterman    schedule 25.07.2011
comment
Можете ли вы опубликовать код вызова (вокруг RunWorkerAsync(null))?   -  person Henk Holterman    schedule 25.07.2011
comment
(После комментариев ниже) — опубликуйте весь код, относящийся к clientSocket. Без него этот вопрос неразрешим.   -  person Henk Holterman    schedule 26.07.2011


Ответы (2)


В документации указано, что XmlReader.Create считывает первые несколько байтов для определения кодировки.
Я думаю, проблема в том, что ваш поток не возвращает никаких данных. Это может быть связано с тем, что другой поток уже прочитал все данные.

person Daniel Hilgarth    schedule 25.07.2011
comment
Но именно в этом проблема. Если я не использую backgroundWorker, он работает нормально. Например, если я заключаю метод в событие щелчка мыши, он работает так, как должен. Есть ли что-то, что мне нужно сделать, чтобы xmlReader работал с backgroundWorker? - person snaee; 25.07.2011
comment
@Henk: Ваш комментарий подразумевает, что вы думаете, что я неправильно прочитал его вопрос. Ты неправ. Прочитайте мой ответ еще раз: это может быть так, потому что другой поток уже прочитал все данные. Когда он использует свой код в потоке пользовательского интерфейса, (скорее всего) есть только один поток. Теперь он вводит BackgroundWorker и у него есть два потока. Непосредственно после вызова BackgroundWorker поток пользовательского интерфейса мог продолжить чтение сетевого потока, что могло вызвать его проблему. - person Daniel Hilgarth; 25.07.2011
comment
@Daniel: Единственное место, где я вызываю xmlReader.Create, — это backgroundWorker. Возможно ли, что поток пользовательского интерфейса читает поток? Если да, то как я могу это исправить? - person snaee; 25.07.2011
comment
@snaee: Пожалуйста, покажите код обработчика нажатия кнопки, как уже попросил Хенк. - person Daniel Hilgarth; 25.07.2011
comment
Вот оно: private void startScan_Click(отправитель объекта, EventArgs e) { backgroundWorker1.RunWorkerAsync(null);} - person snaee; 25.07.2011
comment
@snaee: клиентский сокет используется где-то еще? - person Daniel Hilgarth; 26.07.2011
comment
Нет, больше нигде не используется. Я включил метод MessageBox.Show() в BackgroundWorker1, и он указывает, что процесс выполняется без проблем, описанных ранее. Пока я продолжаю нажимать кнопку «ОК» в MessageBox, программа продолжает работать нормально. Затем я заменил MessageBox методом backgroundWorker1.ReportProgress() и создал private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {readTagID.Text = y;}, но это, похоже, ничего не делает (в текстовом поле ничего не написано) даже хотя для WorkerReportsProgress установлено значение true. - person snaee; 26.07.2011
comment
@snaee Я думаю, вы, вероятно, слишком часто вызываете ProgressChanged, что вызовет некоторые -не вызывать-чаще-чем-1-секунду?forum=vbgeneral" rel="nofollow noreferrer">проблема. Вы можете добавить System.Threading.Thread.Sleep(500); перед backgroundWorker1.ReportProgress. - person 劉鎮瑲; 20.02.2019

Похоже, создание средства чтения XML блокируется при чтении потока.

  • Может возникнуть тупиковая ситуация, когда серверный поток не будет отправлять байты до тех пор, пока фоновый рабочий поток не выполнит какую-либо задачу (однако кажется маловероятным).

  • Как предполагает @Daniel Hilgarth, возможно, другой поток ранее полностью прочитал поток?

Здесь также могут быть некоторые проблемы с синхронизацией. Попробуйте добавить оператор блокировки вокруг кода, например: -

private readonly object streamLocker = new object();

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    lock(streamLocker)
    {
        NetworkStream serverStream = clientSocket.GetStream();
        XmlReader r = XmlReader.Create(serverStream);

        while (r.Read())
        {
          //  output something using backgroundWorker1.ReportProgress object
        }
    }
}
person ljs    schedule 25.07.2011
comment
Я пробовал оператор блокировки, но это не сработало. Как и другие (@Henk...), предположили, что backgroundWorker может пытаться получить доступ к потоку после того, как поток пользовательского интерфейса прочитал данные. Это может быть проблемой, но я не знаю, где поток пользовательского интерфейса считывает данные, поскольку единственное место, где я вызываю XMLReader.Create, находится в backgroundWorker.... - person snaee; 25.07.2011