【发布时间】:2011-01-12 13:58:37
【问题描述】:
我正在开发一个 WPF .NET 3.5 应用程序,该应用程序执行一些长任务,我想为 UI 线程创建一个单独的线程来处理数据,然后在完成后更新 UI 中的一些标签。我遇到的问题是我的函数使用了两个参数,我正在努力研究如何在线程中调用具有多个参数的函数并更新 UI。
我一直在尝试使用 Delegate Sub 来调用函数(它位于单独的类中),并且我的代码还尝试从函数返回数据集以供调用线程更新 UI,但是我不确定这是否是实现这一目标的最佳实践,或者我是否应该为被调用函数使用调度程序来进行 UI 更新(非常感谢反馈)。
我的代码如下。
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
我的问题是,如果我要让调用线程更新 UI,我如何让被调用线程返回数据集,或者如果被调用线程要更新 UI,我该如何实现呢?
更新:
根据提供的建议,我实现了一个 BackgroundWorker,它引发 DoWork 和 RunWorkerCompleted 事件以分别获取数据和更新 UI。我的更新代码如下:
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 事件(至少函数没有)。
谁能提供一些帮助,帮助我调试代码,看看为什么这些函数没有被调用?
另外,上面的代码是答案中推荐的正确方法吗?
我们将不胜感激。
马特
【问题讨论】:
-
我已经更新了问题,我已经按照建议实现了 BackgroundWorker,但是我在获取这两个函数来处理 DoWork 和 RunWorkerCompleted 事件时遇到了问题。
标签: wpf multithreading .net-3.5 dispatcher