#c# #.net
Вопрос:
Я знаю, что только поток графического интерфейса может обновлять компонент пользовательского интерфейса, и для вычисления длительных задач мы должны использовать пул потоков для выполнения тяжелой работы и создания задачи продолжения для обновления пользовательского интерфейса с помощью планировщика задач контекста синхронизации.
Вот простое приложение Windows Forms
internal sealed class MyForm : Form
{
private readonly TaskScheduler m_syncContextTaskScheduler;
public MyForm()
{
m_syncContextTaskScheduler =
TaskScheduler.FromCurrentSynchronizationContext();
Text = "Synchronization Context Task Scheduler Demo";
}
protected override void OnMouseClick(MouseEventArgs e)
{
// This task uses the default task scheduler and executes on a thread pool thread
Task<Int32> t = Task.Run(...);
// This task uses the sync context task scheduler and execute on the GUI thread
t.ContinueWith(task => Text = "Result: " task.Result,
CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion,
m_syncContextTaskScheduler);
...
base.OnMouseClick(e);
}
}
Мой вопрос довольно прост: какой поток для этого запускает код, например OnMouseClick
метод? Является ли сам поток графического интерфейса, выполняющий этот код, поэтому задействованы только два потока, один поток графического интерфейса и один рабочий поток? или рабочий поток запускает этот код, поэтому задействованы один поток графического интерфейса и два рабочих потока?
Ответ №1:
Обработчики для событий, созданных пользовательским интерфейсом, выполняются в потоке пользовательского интерфейса. Таким образом, в вашем коде OnMouseClick
также будет выполняться поток пользовательского интерфейса. Он Task
будет выполняться в потоке, определенном планировщиком (как правило, это будет поток пула потоков).
Технически, некоторый код может вызывать ваш OnMouseClick
в потоке, отличном от пользовательского интерфейса, но это плохая практика, и стандартные элементы управления WinForms/WPF не будут делать такие вещи.
Также обратите внимание, что пул потоков обычно содержит более одного потока для выполнения задач.
Ответ №2:
Я провел простой тест в своем простом приложении WPF, как в моем ctor MainWindow (), так и в моем btnMouseClick (), я распечатал идентификатор потока {System.Threading.Thread.CurrentThread.ManagedThreadId}
, и оба из них ставят 1, как вы можете себе представить. Так что да, поток графического интерфейса выполняет код в вашем OnMouseClick
, тогда ваша новая задача находится в рабочем потоке.