Синхронизация потоков

В WPF есть такое понятие как

Диспатчеризация

.

Диспатчер -- это UI-поток Вашего приложения. Когда Вы запускаете приложение в первый раз ему присваивается поток.

Какой именно поток присвоить приложению решает операционная система.

По своей сути WPF приложение -- однопоточное.

Когда Вы пытаетесь из одного потока что-то изменить в главном потоке (в UI-потоке) -- будет ошибка.

Например Вы пытаетесь задать текст TextBox'у из другого потока, но дело в том, что в другом потоке нет этого TextBox'а.

Тут возникает конфликт.

C#Выделить код

1
2
3
4
5
6
7
8
9
10
11
12
13

         //Task.Run -- перешёл в другой поток
        Task.Run(() => 
        {
            try
            {
                //Из другого потока птыаюсь обратиться к myTextBox.Text
                myTextBox.Text += "Hello, world!";
            }
            catch (Exception ex)
            {
                // Тут будет отловлена ошибка {"The calling thread cannot access this object because a different thread owns it."}
            }
        });

Это всё равно что одной ложкой одновременно мешать чай в двух кружках.

Нет, так не получится. Нужно из первой чашки перелить чай во вторую и уже тогда мешать ложкой.

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

Вы можете получить гланый поток Вашего UI-приложения с помощью

Application.Current.Dispatcher

и выполнить Ваш код именно в нём:

C#Выделить код

1
2
3
4
5
6
7
8
9
10

        Application.Current.Dispatcher.BeginInvoke(() =>
        {
            // Тут Ваш код из другого потока:
        });
 
        //Или же так, если у Вас асинхронная задача ожидающая результата
        await Application.Current.Dispatcher.InvokeAsync(async() =>
        {
            // Тут Ваш код из другого потока:
        });

Касательно

Thread

. Это слишком затратный процесс. Thread используется для каких-то масштабных задач, например создание нового, "тяжелого" окна. В вашем же случае нужно использовать

Task

.

Добавлено через 4 минуты

Task использует один из пулла уже созданных потоков, а Thread создаёт новый поток.

Создание потока -- очень ресурсоёмкий процесс.