UI仍然使用backgroundWorker冻结

时间:2013-01-25 16:43:56

标签: c# wpf multithreading backgroundworker

我对WPF很新。我正在开发一个PRISM应用程序,并希望在更新可枚举时更新UI。 我在modelView中使用backgroundWorker来更新enumaration。它一切正常,直到它自我更新的枚举,然后UI冻结! 一位朋友告诉我,我可能可以使用yield关键字,但我并没有想出来。

以下是代码:

public void ChangeCollection()
    {
        BackgroundWorker worker = new BackgroundWorker();

        // Set workers job
        worker.DoWork += (sender, e) =>
            {
                RunOnUIThread(() => IsBusy = true);
                e.Result = GetPrimes();
            };

        // On Complete
        worker.RunWorkerCompleted += (sender, e) =>
            {
                RunOnUIThread(() =>
                    {
                        IsBusy = false;

                        // HERE IS WHERE IT GETS STUCK
                        Numbers = new ObservableCollection<int>
                            ((IEnumerable<int>)e.Result);
                    });
            };

        // Start background operation
        worker.RunWorkerAsync();
    } 

    public ObservableCollection<int> Numbers 
    { 
        get {return _Numbers;} 
        set
        {
            _Numbers = value;
            RaisePropertyChanged(() => Numbers);
        }
    }

    public IEnumerable<int> GetPrimes()
    {
        List<int> primes = new List<int>();

        for (int i = 0; i < 100000; i++)
        {
            bool IsPrime = true;

            for (int j = 2; j < i; j++)
            {
                if (i % j == 0)
                    IsPrime = false;
            }

            if (IsPrime)
                primes.Add(i);
        }

        return primes;
    } 

任何建议都会受到很大关注!

谢谢, Omri

2 个答案:

答案 0 :(得分:0)

yield在这里不会帮到你。 RunWorkerCompleted在UI线程上执行。显然实例化ObservableCollection<int>需要很长时间。最简单的解决方案可能是将实例化移动到后台线程(DoWork)。它也可能是一个PropertyChanged事件处理程序需要很长时间,在这种情况下它也应该在后台线程上运行。

答案 1 :(得分:0)

这里有一些事情。 1)当您的包含它的对象被实例化时,应该创建您的worker及其委托。

public class ViewModel 
{
    BackgroundWorker _primeWorker;

    public ViewModel()
    {
        _primeWorker = new BackgroundWorker;

        _primeWorker.DoWork += ...
    }

    public void AddSomeNumbers()
    {
         if(_primerWorker.IsBusy == false)
              _primeWorker.RunWorkerAsync();
    }
}

2)当实例化包含它的对象时,应该实例化您的集合,以避免在使用此类的对象调用get时抛出null异常。

3)添加许多项会导致因每次添加数字而导致缓慢,因此会触发UI线程必须处理的事件。

此链接有更多信息可以帮助您。 http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx