.net WPF MVVM中启动线程查找任务的正确方法

.net WPF MVVM中启动线程查找任务的正确方法,.net,wpf,multithreading,mvvm,.net,Wpf,Multithreading,Mvvm,因此,我有一个任务可以由我的GUI执行,它将提取信息,用SQL数据库查询响应填充ViewModel假设我想启动此任务,并让我的gui自由地进行其他事情,同时播放“搜索”动画,在WPF/MVVM中执行此操作的正确方法是什么?我假设您需要启动一个异步进程,并设置绑定到启动动画情节提要的数据触发器的布尔值但是我用什么来开始这个过程呢?线程?我还是WPF新手,只是想确保我使用的类对我来说是正确的。我使用BackgroundProcess线程来做类似的事情 以下是指向MSDN的链接: 与此相关的其他详细信

因此,我有一个任务可以由我的GUI执行,它将提取信息,用SQL数据库查询响应填充ViewModel假设我想启动此任务,并让我的gui自由地进行其他事情,同时播放“搜索”动画,在WPF/MVVM中执行此操作的正确方法是什么?我假设您需要启动一个异步进程,并设置绑定到启动动画情节提要的数据触发器的布尔值但是我用什么来开始这个过程呢?线程?我还是WPF新手,只是想确保我使用的类对我来说是正确的。

我使用BackgroundProcess线程来做类似的事情

以下是指向MSDN的链接:

与此相关的其他详细信息

有三个事件与BackgroundProcess对象关联:DoWork、ReportProgress和WorkCompleted

现在,要使用它——并将其用于ObservaleCollection——您需要告诉BackgroundProcess对象能够报告进度(这是一个布尔属性,我总是显式设置,同时允许取消)

现在要开始一个进程,您将调用RunWorkerAsync方法。此方法能够在需要传递数据时接受对象变量(如果需要多于1个值,请创建一个要传递到RunWorkerAsync的结构)

RunWorkerAsync触发DoWork事件,因此控制权转移到DoWork事件处理程序。下面是我使用它的(净化)代码:

Dim dt As System.Data.DataTable
dt = da.GetDataTable(sql, System.Data.CommandType.Text, params)
For Each row As System.Data.DataRow In dt.Rows
   If loadQuestionsWorker.CancellationPending Then
       e.Cancel = True
       Exit Sub
   End If
   Dim item As New DataObject
   // Assign Item Values
   backgroundProcessObject.ReportProgress(1, item)
Next
这里发生的事情是,我从我的数据层获取一个数据表,然后当这个背景过程没有被取消时,我在遍历数据表,当我构建一个新的数据对象时,我报告该对象正在构建

现在,在我的ProgressChanged事件处理程序(ReportProgress方法引发ProgressChanged事件)中,控件又回到了UI线程的手中,因此我可以做一些事情,比如影响UI并将我报告的元素添加到ObservableCollection


最后,在我的WorkedCompleted事件处理程序(当DoWork事件处理程序方法运行到完成时引发相应的事件)中,我检查我的进度是否被取消(这有时意味着我要转储ObservableCollection),我可能会也可能不会影响UI(例如删除“搜索”)动画。

您可以显式启动一个新的
线程
BackgroundWorker
,或者使用
线程池
。我不知道在MVVM中有什么推荐的方法


如果您的异步操作正在填充绑定到控件的ObserveCollection,请注意,您不能在其他线程上向其添加项。您需要在控件的dispatcher线程上执行此操作。或者您也可以使用,这会在适当的线程上引发CollectionChanged事件

我想我在这里遇到了与Observ相关的问题我的代码是基于MVVM的,因此我的工作人员正在对视图模型进行更改…该视图模型绑定到UI元素…因此它被锁定。绑定标量属性可以跨线程正常工作,更改通知会自动在正确的线程上封送。对于集合,它不受支持。请参阅我为您提供的链接r一个可能的解决方案我做错了,去线程,看看这个,然而我真的很喜欢这个。
var t = new Thread((ThreadStart)delegate
{
    DoWork(...)
    Dispatcher.BeginInvoke((Action)delegate
    {
          SomethingOntheUiThread(...)
          FinishedWork(...);
    }
});

t.Start();