MVVM中,如何防止BackgroundWorker卡死UI?首先,我在SO和网络上看到了很多类似的问题。这些似乎都不能解决我的特定问题。我有一个简单的BackgroundWorker,它的工作是逐行读取文件并报告进度以指示它有多远。文件中共有65,553行,因此BackgroundWorker尽快完成对我来说很重要。由于MVVM是建立在关注点分离(SoC)和视图与视图模型分离的基础上的,因此BackgroundWorker会更新视图绑定到的视图模型上的属性。我的设置与KentBoorgaart在另一个问题上的回答非常相似。在高压力情况下,BackgroundWorker在没有休眠的情况下需要大量CPU,UI线程处于饥饿状态并且无法更新已通过INotifyPropertyChanged通知的任何绑定属性。但是,如果BackgroundWorker休眠,作业将不会很快完成。如何确保View在尊重MVVM的同时接收进度更新,同时不限制工作?在View-Model中,BackgroundWorker设置如下。Start()函数由RelayCommand调用(MVVM-LightStart()的一部分。publicvoidStart(stringmemoryFile){this.memoryFile=memoryFile;BackgroundWorkerworker=newBackgroundWorker();worker.DoWork+=Worker_DoWork;worker.ProgressChanged+=Worker_ProgressChanged;worker.WorkerReportsProgress=true;worker.RunWorkerAsync();}下面是实际工作的代码:privatevoidWorker_DoWork(objectsender,DoWorkEventArgse){BackgroundWorkerbw=(BackgroundWorker)sender;IsAnalyzing=真;bw.ReportProgress(0,newProgressState("Processing..."));intcount=File.ReadLines(memoryFile).Count();StreamReaderreader=newStreamReader(memoryFile);字符串行="";int行索引=0;while((line=reader.ReadLine())!=null){bw.ReportProgress((int)(((double)lineIndex/count)*100.0d));//处理记录...(假设耗时操作)HexRecordrecord=HexFileUtil.ParseLine(line);行索引++;if(lineIndex%150==0){//取消注释给UI线程一些时间。//但是,这会限制工作。//线程.睡眠(5);}}bw.ReportProgress(100,newProgressState("Done."));线程.睡眠(1000);IsAnalyzing=false;}privatevoidWorker_ProgressChanged(objectsender,ProgressChangedEventArgse){Progress=e.ProgressPercentage;if(e.UserState!=null){Task=((ProgressState)e.UserState).Task;在上面的代码中,以下属性用于View和View-Model之间的绑定,每个属性都会触发INotifyPropertyChanged.PropertyChanged事件:编辑:在StephenCleary和FilipTask.Run()的后续行动中,我尝试了在有和没有ObservableProgress的情况下使用Task.Run()我已经简化了后台任务以迭代数字而不是文件行。privatevoidDoWork(IProgressprogress){IsAnalyzing=true;progress.Report(newProgressState(0,"处理中..."));对于(inti=0;i<2000000000;i+=1000000){intpercent=(int)(((double)i/2000000000)*100.0d);progress.Report(newProgressState(percent,String.Format("Processing({0}%)",percent)));线程.睡眠(5);}progress.Report(newProgressState(100,"Done."));线程.睡眠(1000);IsAnalyzing=false;现在,我用一种或两种方式启动任务(使用或不使用ObservableProgress):publicvoidStart(stringmemoryFile){this.memoryFile=memoryFile;/*TODO:取消注释此部分以改用ObservableProgress。ObservableProgress.CreateAsync(progress=>System.Threading.Tasks.Task.Run(()=>DoWork(progress))).Sample(TimeSpan.FromMilliseconds(50)).ObserveOn(Application.Current.Dispatcher).Subscribe(p=>{Progress=p.ProgressPercentage;Task=p.Task;});*///TODO:评论此部分以改用ObservableProgress。varprogress=newProgress();progress.ProgressChanged+=(s,p)=>{Progress=p.ProgressPercentage;Task=p.Task;};System.Threading.Tasks.Task.Run(()=>DoWork(进度));}ObservableProgress.cspublicstaticclassObservableProgress{publicstaticIObservableCreateAsync(Func
