Wpf 线程函数具有多个参数并返回数据
我正在开发一个WPF.NET3.5应用程序,它可以执行一些长任务,我想在UI线程中创建一个单独的线程来处理数据,然后在完成后更新UI中的一些标签。我遇到的问题是,我的函数使用了两个参数,我正在努力解决如何在线程中使用多个参数调用函数并更新UI 我一直在尝试使用委托子函数调用函数(它位于一个单独的类中),我的代码还试图从函数返回一个数据集,以便调用线程更新UI,但我不确定这是否是实现这一点的最佳实践,或者我是否应该使用调用函数的调度程序来进行UI更新(非常感谢反馈) 我的代码如下Wpf 线程函数具有多个参数并返回数据,wpf,multithreading,.net-3.5,dispatcher,Wpf,Multithreading,.net 3.5,Dispatcher,我正在开发一个WPF.NET3.5应用程序,它可以执行一些长任务,我想在UI线程中创建一个单独的线程来处理数据,然后在完成后更新UI中的一些标签。我遇到的问题是,我的函数使用了两个参数,我正在努力解决如何在线程中使用多个参数调用函数并更新UI 我一直在尝试使用委托子函数调用函数(它位于一个单独的类中),我的代码还试图从函数返回一个数据集,以便调用线程更新UI,但我不确定这是否是实现这一点的最佳实践,或者我是否应该使用调用函数的调度程序来进行UI更新(非常感谢反馈) 我的代码如下 Priv
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
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
我的问题是,如果要让调用线程更新UI,如何让被调用线程返回数据集,或者如果要让被调用线程更新UI,如何实现这一点
更新:
根据提供的建议,我实现了一个BackgroundWorker,它分别引发DoWork和RunWorkerCompleted事件来获取数据和更新UI。我的更新代码如下:
Class test_global
Public Sub getWeatherData(ByVal filename As String, ByVal location As String) 'As DataSet
...
End Sub
End Class
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行中放置断点时,该行被调用,窗口加载子完成,但似乎没有调用DoWork或RunWorkerCompleted事件(至少函数没有)
有没有人可以提供一些帮助,让我调试代码,看看为什么没有调用这些函数
此外,上述代码是否是答案中建议的正确方法
我们将非常感谢您提供的任何帮助
Matt您应该使用
您应该在DoWork
处理程序中调用函数,并将e.Result
设置为返回的数据集。然后,您可以在
RunWorkerCompleted
处理程序中更新UI。您应该使用
您应该在DoWork
处理程序中调用函数,并将e.Result
设置为返回的数据集。然后,您可以在
RunWorkerCompleted
处理程序中更新UI。我对BackgroundWorker
没有太多经验(我只使用过一次),但它肯定是解决您问题的方法。然而,我经常使用的方法是启动一个新线程(不是通过委托的线程池线程),它获取一个锁,然后更新所有属性。如果类实现了INotifyPropertyChanged,则可以使用数据绑定使GUI在属性更改时自动更新。我用这种方法取得了很好的效果
至于向线程传递调度程序,我相信您也可以这样做。然而,我会轻描淡写,因为我相信我遇到过这样的情况:我认为我正在使用的调度程序不再与主线程关联。我有一个库,需要调用一个涉及GUI元素的方法(即使对话框可能不显示),我使用Dispatcher.Invoke解决了这个问题。我能够保证我使用的是与主线程关联的调度程序,因为我的应用程序使用MEF导出它
如果您想了解我发布的任何内容的更多详细信息,请发表评论,我会尽我所能对这些主题进行润色。我对
BackgroundWorker
没有太多经验(我只使用过一次),但这绝对是解决您问题的方法。然而,我经常使用的方法是启动一个新线程(不是通过委托的线程池线程),它获取一个锁,然后更新所有属性。如果类实现了INotifyPropertyChanged,则可以使用数据绑定使GUI在属性更改时自动更新。我用这种方法取得了很好的效果
至于向线程传递调度程序,我相信您也可以这样做。然而,我会轻描淡写,因为我相信我遇到过这样的情况:我认为我正在使用的调度程序不再与主线程关联。我有一个库,需要调用一个涉及GUI元素的方法(即使对话框可能不显示),我使用Dispatcher.Invoke解决了这个问题。我能够保证我使用的是与主线程关联的调度程序,因为我的应用程序使用MEF导出它
如果您想了解我发布的任何内容的更多详细信息,请发表评论,我将尽我所能对这些主题进行润色。请使用
BackgroundWorker
。实现长时间运行的方法,并将参数传递给DoWork
事件处理程序的DoWorkEventArgs
参数中的方法。在此方法中,不要直接或间接地更新UI(即不要更新视图模型的属性)
使用进度报告在方法运行时更新UI:在长时间运行的方法中调用ReportProgress
,在UserState
参数中传递需要显示在UI中的任何信息。在ProgressChanged
事件处理程序中,从progresschangedventargs
获取状态并更新UI(希望通过更新视图模型的适当属性并引发PropertyChanged
)
您需要实现一个类来包含进度报告的用户状态,因为UserState
属于object
类型