Я прочитав багато вступних статей про те, як оновити основний інтерфейс у фоновому треді, і більшість із них використовують Control.Invoke та Control.BeginInvoke. Це хороші рішення, але є дві проблеми:
1. Ви повинні посилатися на System.Windows.Forms, а потім скористатися System.Windows.Forms
2. Структура коду досить хаотична. (Насправді, це також спричинено #1)
Microsoft пропонує ще одне, більш елегантне рішення — System.Threading. SynchronizationContext。 Як бачите, його немає у namesapce System.Windows.Forms, тому ми можемо справедливо використовувати його в BusinessLaryer, Control і навіть модулях.
І він дуже зручний у використанні, потрібно зосередитися лише на двох методах:
1. Відправити: надсилає запит на оновлення інтерфейсу до основного потоку, блокуючи поточний потік до його повернення.
2. Пост: надсилає запит на оновлення інтерфейсу до основного потоку без блокування поточного потоку.
Насправді всі вони однакові методи, за винятком того, що send є синхронним, а post — асинхронним
До появи Form1 form = new Form1(), об'єкт SynchronizationContext був порожнім, і при створенні форми Form1 до цього потоку додавався об'єкт SynchronizationContext. Отже, відповідь полягає в тому, що коли створено об'єкт Control, об'єкт SynchronizationContext також створюється і приєднується до потоку. Все це при використанні форми InitializeComponent(); Після цього можна отримати об'єкт, який не є NULL
Нарешті, різниця між методами Sendt() і Post() у SynchronizationContext:
Send() реалізується простим викликом делегата поточного потоку (синхронний виклик). Тобто потік UI безпосередньо викликається на підпотоці для виконання, і підпотік продовжує виконувати його після завершення виконання потоку UI.
Post() реалізується шляхом виклику делегата у пулі потоків (асинхронний виклик). Це тому, що підпотік знаходить потік із пулу потоків для налаштування UI-потоку, і підпотік безпосередньо виконує власний код, не чекаючи завершення UI-потоку. Тестовий код:
Результат:
Основна тема інтерфейсу: 1 Тема: 5 SynchContext:1
Зведення:Об'єкт SynchronizationContext у UI-потоці, незалежно від того, викликається він у основному потоці чи в ньому, виконується на основному потоці, тому при великій кількості часу коду інтерфейс інтерфейсу UI зависає або імітується смерть!
НасправдіПотік інтерфейсу використовує не клас SynchronizationContext, а WindowsFormsSynchronizationContextЦей Дондонг.
Вихідний код System.Threading.SynchronizationContext:
Вихідний код WindowsFormsSynchronizationContext:
|