每次计时器调用UpdateDocumentsListFromServer UI时,冻结3秒。如何在.net 3.5下以异步方式更新列表?
ViewModel:
public class ShippingDocumentsRegisterViewModel : ViewModelBase
{
ShippingDocumentsModel model = new ShippingDocumentsModel();
DispatcherTimer timer = new DispatcherTimer();
BackgroundWorker BW = new BackgroundWorker();
public ShippingDocumentsRegisterViewModel()
{
timer = new DispatcherTimer();
timer.Tick += new EventHandler(UpdateDocumentsListFromServer);
timer.Interval = new TimeSpan(0, 0, 10);
timer.Start();
this.Columns = model.InitializeColumns();
BW.DoWork += UpdateDocumentsList;
BW.RunWorkerAsync();
}
public void UpdateDocumentsList(object o, EventArgs args)
{
this.ShippingDocuments = model.GetDocuments();
}
public void UpdateDocumentsListFromServer(object o, EventArgs args)
{
// Taking a lot of time. How to do it async?
var tempDocuments = model.GetDocumentsFromServer();
foreach (var item in tempDocuments)
{
this.shippingDocuments.Add(item);
}
//
}
private ObservableCollection<ShippingDocument> shippingDocuments;
public ObservableCollection<ShippingDocument> ShippingDocuments
{
get
{
return shippingDocuments;
}
private set
{
shippingDocuments = value;
RaisePropertyChanged("ShippingDocuments");
}
}
public ObservableCollection<ShippingDocumentColumDescriptor> Columns { get; private set; }
}GetDocumentsFromServer看起来像
public ObservableCollection<ShippingDocument> GetDocumentsFromServer()
{
System.Threading.Thread.Sleep(3000);
return new ObservableCollection<ShippingDocument> { new ShippingDocument { Name = "Test" } };
}发布于 2016-07-25 13:49:52
还可以使用向UI报告进度的后台工作人员。
public ShippingDocumentsRegisterViewModel()
{
BW.DoWork += UpdateDocumentsListFromServer;
BW.RunWorkerCompleted += BW_RunWorkerCompleted;
BW.WorkerReportsProgress = true;
BW.ProgressChanged += UpdateGui;
BW.RunWorkerAsync();
}
public void UpdateGui(object o, EventArgs args)
{
foreach (var item in tempDocuments)
{
this.shippingDocuments.Add(item);
}
}
public void UpdateDocumentsListFromServer(object o, EventArgs args)
{
while (true) {
System.Threading.Thread.Sleep(3000);
tempDocuments = GetDocumentsFromServer();
BW.ReportProgress(0);
}
}
int num = 0;
public ShippingDocument[] GetDocumentsFromServer()
{
System.Threading.Thread.Sleep(3000);
return new ShippingDocument[1] { new ShippingDocument { Name = "Test" + num++} };
}
private ShippingDocument[] tempDocuments = new ShippingDocument[0];发布于 2016-07-26 01:07:31
只需使用任务和异步/等待将其卸载到一个新线程,如下所示:
public async void UpdateDocumentsListFromServer(object o, EventArgs args)
{
// This will execute async and return when complete
await Task.Run(()=>{
var tempDocuments = model.GetDocumentsFromServer();
foreach (var item in tempDocuments)
{
this.shippingDocuments.Add(item);
}
});
//
}请记住,这是在不同线程上更新的,然后是UI。因此,它不允许在UI线程上接触任何东西,否则您会遇到线程问题。因此,如果shippingDocuments是在UI线程上创建的,而不是线程安全的,则可以返回一组项,然后添加它们:
public async void UpdateDocumentsListFromServer(object o, EventArgs args)
{
// Execute on background thread and put results into items
var items = await Task.Run(()=>{
var tempDocuments = model.GetDocumentsFromServer();
return tempDocuments;
});
//add occurs on UI thread.
this.shippingDocuments.AddRange(tempDocuments);
}发布于 2016-07-25 12:45:46
使用常规的Timer,并且只分配对shippingDocuments的访问。
https://stackoverflow.com/questions/38567935
复制相似问题