Почему Crossthreading работает таким образом?

решаемые

Кажется, что Оливер прав. После нескольких попыток я получил исключение, и в режиме отладки я получаю это точно. Так что это должно быть все время. Вы также должны проверить ответ Мэтью Ваттонса;)

Пример

Прежде всего небольшой пример, который объяснит мое замешательство.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace testCrossThreading
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            new Thread(ThreadJob).Start();
        }

        void ThreadJob()
        {
            //label1.Text = "1";
            changeText(label1, "1");
        }

        void changeText(Label L, String message)
        {
            L.Text = message;
        }
    }
}

Вопрос

Итак, теперь мой вопрос: если я раскомментирую label1.Text = "1"; в функции "ThreadJob", тогда я получаю исключение перекрестного потока, как ожидалось. Но если я оставлю его прокомментированным, как показано на примере, он действительно работает. Но почему? Функция вызывается вспомогательным потоком, и я ничего не вызываю. Таким образом, это все еще вспомогательный поток, а не поток GUI, который изменяет текст метки imo. Или я что-то упускаю?

Я бы написал это так.

void ThreadJob()
        {
            Action a = () => label1.Text = "1";
            this.Invoke(a);
        }

Ответ 1

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

Form.CheckForIllegalCrossThreadCalls = false;

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

Ответ 2

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

Если вы попытаетесь изменить свойство Text элемента управления, который в настоящее время не отображается, тогда .Net не заботится о том, какой поток меняет его.

В вашем коде вы начинаете поток с конструктора. Код, который фактически отображает форму, может отображаться или не отображаться перед тем, как код в потоке, который устанавливает свойство, выполняется.

Когда вы вызываете дополнительную функцию для установки свойства, тайминги изменяют и выставляют условия гонки.

Вы можете проверить это, добавив Thread.Sleep(100) в начало ThreadJob().