Практическое руководство. Сделать потокобезопасных вызовов элементов управления Windows Forms
Многопотоковость позволяет повысить производительность приложений Windows Forms, но доступ к элементам управления Windows Forms не по своей природе потокобезопасными. Многопоточность можно предоставить код, чтобы очень серьезных и сложных ошибок. Два или более потоков, управление элементом управления можно перевести в несогласованном состоянии и привести к гонки, взаимоблокировки и перестает отвечать или зависает. При реализации многопоточности в приложении, убедитесь, что для вызова элементов управления между потоками в потокобезопасным способом. Дополнительные сведения см. в разделе управляемых потоков рекомендации.
Безопасно вызвать элемент управления Windows Forms из потока, который не создавали этого элемента управления двумя способами. Можно использовать System.Windows.Forms.Control.Invoke метод для вызова делегата, созданного в основном потоке, который в свою очередь вызывает элемент управления. Или можно реализовать System.ComponentModel.BackgroundWorker, который использует модель на основе событий для разделения работы, выполненной в фоновом потоке из отчетов о результатах.
Ориентированные вызовы между потоками
Вызов элемента управления непосредственно из потока, который не создавали его небезопасно. В следующем фрагменте кода показано небезопасный вызов System.Windows.Forms.TextBox элемента управления. Button1_Click
Обработчик событий создает новую WriteTextUnsafe
поток, который задает основной поток TextBox.Text свойство напрямую.
private void Button1_Click(object sender, EventArgs e)
{
thread2 = new Thread(new ThreadStart(WriteTextUnsafe));
thread2.Start();
}
private void WriteTextUnsafe()
{
textBox1.Text = "This text was set unsafely.";
}
Private Sub Button1_Click(ByVal sender As Object, e As EventArgs) Handles Button1.Click
Thread2 = New Thread(New ThreadStart(AddressOf WriteTextUnsafe))
Thread2.Start()
End Sub
Private Sub WriteTextUnsafe()
TextBox1.Text = "This text was set unsafely."
End Sub
Отладчик Visual Studio обнаруживает эти вызовы небезопасный потока, вызывая InvalidOperationException с сообщением, не является допустимым, операция в нескольких потоках. Элемент управления «» получить доступ из потока, отличного от потока, он был создан. InvalidOperationException Всегда возникает ориентированные вызовы между потоками во время отладки Visual Studio и может возникнуть во время выполнения приложения. Вам следует устранить проблему, однако исключение можно отключить, установив Control.CheckForIllegalCrossThreadCalls свойства false
.
Безопасные вызовы между потоками
В следующих примерах кода демонстрируются два способа безопасно вызвать элемент управления Windows Forms из потока, который не создавали его:
- System.Windows.Forms.Control.Invoke Метод, который вызывает делегат из основного потока для вызова элемента управления.
- Объект System.ComponentModel.BackgroundWorker компонент, который предоставляет модель на основе событий.
В обоих примерах фона поток бездействует одну секунду имитировать работу, выполняемую в этом потоке.
Можно создавать и запускать эти примеры приложений .NET Framework из C# или командной строки Visual Basic. Дополнительные сведения см. в разделе сборка с помощью csc.exe из командной строки или построения из командной строки (Visual Basic).
Начиная с .NET Core 3.0, вы можете также создавать и выполнять примеры как Windows приложений .NET Core из папки с .NET Core Windows Forms <имя_папки > .csproj файл проекта.
Пример Метод Invoke с помощью делегата
Ниже приведен пример шаблона для обеспечения потокобезопасных вызовов к элементу управления Windows Forms. Он запрашивает System.Windows.Forms.Control.InvokeRequired свойство, которое сравнивает элемент управления создание идентификатор потока, чтобы идентификатор вызывающего потока. Если идентификаторы совпадают, он вызывает элемент управления напрямую. Если идентификаторы различаются, он вызывает Control.Invoke метод с делегатом из основного потока, который выполняет фактический вызов к элементу управления.
SafeCallDelegate
Позволяет задавать TextBox элемента управления Text свойство. WriteTextSafe
Запросы метод InvokeRequired. Если InvokeRequired возвращает true
, WriteTextSafe
передает SafeCallDelegate
для Invoke метод фактически вызывающим элемент управления. Если InvokeRequired возвращает false
, WriteTextSafe
задает TextBox.Text напрямую. Button1_Click
Обработчик событий создает новый поток и запускает WriteTextSafe
метод.
Warning
It looks like the sample you are looking for does not exist.
Пример Используйте обработчик событий компонента BackgroundWorker
Простой способ реализации многопоточности является с System.ComponentModel.BackgroundWorker компонент, который использует модель на основе событий. Фоновый поток запускает BackgroundWorker.DoWork событие, которое не взаимодействует с основным потоком. Основной поток выполняет BackgroundWorker.ProgressChanged и BackgroundWorker.RunWorkerCompleted обработчиков событий, которые можно вызывать элементы управления в основном потоке.
Звонки с потоками с помощью BackgroundWorker, создать метод в фоновый поток для выполнения работы и привяжите его к DoWork событий. Создайте другой метод в основном потоке, передавать результаты фоновой работы и привяжите его к ProgressChanged или RunWorkerCompleted событий. Чтобы запустить фоновый поток, вызовите BackgroundWorker.RunWorkerAsync.
В примере используется RunWorkerCompleted обработчик событий, чтобы задать TextBox элемента управления Text свойство. В качестве примера использования ProgressChanged событий, см. в разделе BackgroundWorker.
Warning
It looks like the sample you are looking for does not exist.