我正在使用VS2012、WPF和MVVM进行TPL。我有一个问题,我认为我知道答案,但想确定一下。请考虑以下代码片段:
TaskCanceller = new CancellationTokenSource();
TaskLoader = Task<object>.Factory.StartNew(() =>
{
//Test the current query
DataRepository dr = new DataRepository(DataMappingSelected);
string test = dr.TestMappingConnection();
if (test.IsNotNullEmpty())
throw new DataConnectionException(test);
//Create the CSV File
DataQueryCsvFile CsvFile = new DataQueryCsvFile();
CsvFile.FileName = IO.Path.GetFileName(FilePath);
CsvFile.FilePath = IO.Path.GetDirectoryName(FilePath);
CsvFile.DataMapping = DataMappingSelected;
CsvFile.DataBrowserQuery = DataQueryHolder;
//Allow for updates to the UI
CsvFile.PageExportComplete += (s, e) =>
{
if (TaskCanceller.IsCancellationRequested)
(s as DataQueryCsvFile).IsSaveCancellationRequested = true;
StatusData = String.Format("{0} of {1} Complete", e.ProgressCount, e.TotalCount);
StatusProgress = (100 * e.ProgressCount / e.TotalCount);
};
CsvFile.SaveFile();
return CsvFile;
});
我有一个名为DataQueryCsvFile的类,其意图是基于传递的查询参数创建一个CSV文本文件,其结果可能非常庞大。因此,导出程序会对查询产生的表进行“分页”,以便不会耗尽用户的内存。其中之一的成员是一个名为PageExportComplete的事件,每当写入“页面”到文件中时,比如每次1000条记录时就会触发它。下面的代码使用此事件来更新UI上的进度指示器。
状态数据和状态进度指示器(StatusData和StatusProgress)在VM中声明,并通过适当的通知让View知道它们何时被更改。例如:
public string StatusData
{
get { return _StatusData; }
set { NotifySetProperty(ref _StatusData, value, () => StatusData); }
}
private string _StatusData;
这是我的问题 - 目前,这个代码能够正常工作。但是我并没有在ContinueWith中声明Task要通过UI线程(FromCurrentSynchronizationContext)运行或更新。
是否因为MVVM模式?换句话说,被更新的属性是VM本地的,并且它们有通知机制用于更新视图,由于通过绑定实现了解耦,所以才起作用?还是仅仅因为特殊情况而侥幸成功,我应该费劲地声明一个ContinueWith来在UI线程上更新进度呢?
INPC
来实现。绑定引擎在内部侦听该事件,并且可能会在UI调度程序上更新UI对象,从而避免任何跨线程问题。 - Rohit Vats