Я работаю над приложением WPF .NET 3.5, которое выполняет несколько длинных задач, которые я хотел бы сделать отдельным потоком для потока пользовательского интерфейса для обработки данных, а затем по завершении обновить некоторые метки в пользовательском интерфейсе. Проблема, с которой я сталкиваюсь, заключается в том, что функция, которую я использую, использует два параметра, и я изо всех сил пытаюсь понять, как вызвать функцию с несколькими параметрами в потоке и обновить пользовательский интерфейс.
Я играл с использованием Delegate Sub для вызова функции (она находится в отдельном классе), и мой код также пытался вернуть набор данных из функции для вызывающего потока для обновления пользовательского интерфейса, но я не уверен, что это лучшая практика для достижения этого, или мне следует использовать диспетчер для вызываемой функции для обновления пользовательского интерфейса (обратная связь будет очень признательна).
Мой код выглядит следующим образом.
Private Delegate Sub WorkHandler(ByVal input1 As String, ByVal input2 As String)
Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim test_helper As New test_global
Dim worker As New WorkHandler(AddressOf test_helper.getWeatherData)
worker.BeginInvoke("IDA00005.dat", "Adelaide", AddressOf weatherCallBack, Nothing)
' The following is what I was using prior to attempting to work with threads, do I continue to update the UI here getting the called function to return a dataset, or do I have the called function do the UI updating?
'Dim ls As DataSet = test_helper.getWeatherData("IDA00005.dat", "Adelaide")
'Dim f_date As String = ls.Tables("weather").Rows(1).Item(3).ToString
End Sub
Public Sub weatherCallBack(ByVal ia As IAsyncResult)
CType(CType(ia, Runtime.Remoting.Messaging.AsyncResult).AsyncDelegate, WorkHandler).EndInvoke(ia)
End Sub
И моя функция, которую я пытаюсь вызвать, выглядит следующим образом:
Class test_global
Public Sub getWeatherData(ByVal filename As String, ByVal location As String) 'As DataSet
...
End Sub
End Class
Моя проблема заключается в том, что если бы я должен был иметь вызывающий поток для обновления пользовательского интерфейса, как мне заставить вызываемый поток возвращать набор данных или если вызываемый поток должен обновлять пользовательский интерфейс, как мне это сделать?
Обновление:
Следуя предоставленным рекомендациям, я реализовал BackgroundWorker, который вызывает события DoWork и RunWorkerCompleted для получения данных и обновления пользовательского интерфейса соответственно. Мой обновленный код выглядит следующим образом:
Class Weather_test
Implements INotifyPropertyChanged
Private WithEvents worker As System.ComponentModel.BackgroundWorker
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim test_helper As New test_global
Dim worker = New System.ComponentModel.BackgroundWorker
worker.WorkerReportsProgress = True
worker.WorkerSupportsCancellation = True
Dim str() = New String() {"IDA00005.dat", "Adelaide"}
Try
worker.RunWorkerAsync(str)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub worker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles worker.DoWork
Dim form_Helpder As New test_global
Dim ds As DataSet = form_Helpder.getWeatherData(e.Argument(0), e.Argument(1))
e.Result = ds
End Sub
Private Sub worker_Completed(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted
If e.Error IsNot Nothing Then
MsgBox(e.Error.Message)
Else
...
NotifyPropertyChanged("lbl_minToday")
...
End If
End Sub
End Class
Затем у меня есть в отдельном классе мои функции, которые получают и обрабатывают данные.
Я могу отлаживать код в Visual Studio 2010, и форма отображается, но метки не обновляются, и когда я ставлю точку останова в строке RunWorkerAsync, строка вызывается, и подпрограмма Window_Loaded завершается, но кажется, что ни один из DoWork или События RunWorkerCompleted вызываются (хорошо хоть функции нет).
Может ли кто-нибудь помочь в отладке кода, чтобы понять, почему эти функции не вызываются?
Кроме того, является ли приведенный выше код правильным методом, рекомендованным в ответах?
Любая оказанная помощь будет принята с благодарностью.
Мэтт