Silverlight ViewModel中的BackgroundWorker [英] BackgroundWorker in Silverlight ViewModel

查看:77
本文介绍了Silverlight ViewModel中的BackgroundWorker的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Silverlight视图中有一个TabControl,并且通过将其ItemsSource绑定到ViewModel中的TabItems ObservableCollection来加载Tabs.

I have a TabControl in a Silverlight View and I'm loading Tabs by binding its ItemsSource to a TabItems ObservableCollection in my ViewModel.

要打开一个新标签页,创建它并加载它需要花费一些时间,我想同时运行一个BusyIndi​​cator.

To open a new tab, it takes a little while to create it and load it and I want to run a BusyIndicator meanwhile.

由于它们是在ViewModel中创建和加载的,因此我在调用"load"方法之前设置IsBusy属性不会显示出来,因为它不是异步的.

As they are created and loaded in the ViewModel, it doesn't show up if I set IsBusy property before calling the "load" method because it's not asynchronous.

我试图在后台工作器中进行设置,但是当我创建TabItem并将其添加到TabItems列表(UnauthorizedAccessException)时,它会崩溃.

I've tried to set it in a backgroundworker but it crashes when I create the TabItem to add it to the TabItems list (UnauthorizedAccessException).

有什么主意吗???预先感谢.

Any idea??? Thanks in advance.

推荐答案

使用任务(带有Silverlight 4的AsyncCtp ):

public void Load(){
    this.IsBusy = true;
    Task.Factory.StartNew(()=> DoHeavyWork())
        .ContinueWith( t => this.IsBusy = false);
}

如果您可以将新的异步/等待功能与异步CTP或 VS2012/Silverlight 5

It gets even better if you can use the new async/await features with the Async CTP or with VS2012/Silverlight 5

public async void Load(){
    try{
        this.IsBusy = true;

        await Task.Factory.StartNew(()=> DoHeavyWork());
    }
    finally
    {       
        this.IsBusy = false;
    }
}

编辑

我假设您正在后台任务中更新ObservableCollection.这确实会给您带来问题,因为处理集合更新的处理程序未在UI线程中运行,因此集合更新不像绑定系统那样是线程安全的.为此,您必须将这些项目添加到UI线程中的ObservableCollection.如果您一次可以提取所有商品,则可以执行以下操作:

I assume you are updating the ObservableCollection in the background task. That will indeed give you problems because the handlers that deal with the collection update are not run in the UI thread, so the collection update is not thread safe as the binding system is. For that to work, you will have to add the items to the ObservableCollection in the UI thread. If you can fetch all your items at once, you can do this:

public async void Load(){
    try{
        this.IsBusy = true;

        // Returns the fetched items
        var items = await Task.Factory.StartNew(()=> DoHeavyWork());

        // This will happen in the UI thread because "await" returns the
        // control to the original SynchronizationContext
        foreach(var item in items)
            this.observableCollection.Add(item);
    }
    finally
    {       
        this.IsBusy = false;
    }
}

如果必须分批加载,则可以使用当前分派器将项目添加到集合中,就像我在

If you have to load in batches, you can add the items to the collection using the current Dispatcher, like I suggested in this answer.

这篇关于Silverlight ViewModel中的BackgroundWorker的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆