首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DispatcherTimer WPF异步

DispatcherTimer WPF异步
EN

Stack Overflow用户
提问于 2016-07-25 12:33:37
回答 4查看 6.4K关注 0票数 2

每次计时器调用UpdateDocumentsListFromServer UI时,冻结3秒。如何在.net 3.5下以异步方式更新列表?

ViewModel:

代码语言:javascript
复制
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看起来像

代码语言:javascript
复制
    public ObservableCollection<ShippingDocument> GetDocumentsFromServer()
    {
        System.Threading.Thread.Sleep(3000);
        return new ObservableCollection<ShippingDocument> { new ShippingDocument { Name = "Test" } };
    }
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-07-25 13:49:52

还可以使用向UI报告进度的后台工作人员。

代码语言:javascript
复制
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];
票数 2
EN

Stack Overflow用户

发布于 2016-07-26 01:07:31

只需使用任务和异步/等待将其卸载到一个新线程,如下所示:

代码语言:javascript
复制
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线程上创建的,而不是线程安全的,则可以返回一组项,然后添加它们:

代码语言:javascript
复制
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);
        }
票数 2
EN

Stack Overflow用户

发布于 2016-07-25 12:45:46

使用常规的Timer,并且只分配对shippingDocuments的访问。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38567935

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档