开发者

C# / WPF Databinding and backgroundworkers

Update2

I've rewritten the entire question, because some things became a lot clearer, the issue now seems to be that I created a list of DependencyProperties on a different thread than where the DependencyProperties will be used :(.

When I do some work on a BackgroundWorker the XAML bindings cause an ArgumentException

Must create DependencySource on same Thread as the DependencyObject.

I've got the following setup:

I've got a simple class that implements INotifyPropertyChanged which contains a few ints, list's and Dictionaries.

public class Calculator : INotifyPropertyChanged
{
    //Note that InstanceGroup is a dependency object
    private List<InstanceGroup> instanceGroups = new List<InstanceGroup>();
    public List<InstanceGroup> InstanceGroups
    {
        get { return instanceGroups; }
        set { instanceGroups = value; }
    }

    // snip //

    public void Calculate()
    {
        InstanceGroups = MyNewFilledInstanceGroup;
            if (PropertyChanged != null)
            {
              PropertyChanged(this, new PropertyChangedEventArgs("instanceGroups"));
            }
    }
}

In a UserControl I use a BackgroundWorker to run the Calculate method, because it can take a lot of time:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate(object o, DoWorkEventArgs args)
{
    lock (Calculator)
    {       
        Calculator.Calculate();
    }
};
worke开发者_运维问答r.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();

In the XAML file of the UserControl I have multiple bindings to the Calculator, like {Binding Path=Calculator.InstanceGroups, Path=userControlName}.

(The overall goal is to be able to do all the work in the Calculate method on a separate thread so I can show a progress bar or something like that)


I am not convinced that you need to use DP for this Observable collection. Best to store it in ViewModel.

ObservableCollections are not thread-safe, and you need to use Dispatcher to update the collection.

Google there were some posts with Extension to ObservableCollection which used Dispatcher.

This link might help


Any DependencyObject includes a Dispatcher property that can help you push work to the correct thread for that object.

You can use Dispatcher.Invoke or Dispatcher.BeginInvoke to run code on the correct thread.


The only solution seems to be to not create DependencyProperties ( How to handle ObservableCollection<> result from a parallelized Task in MVVM? ) in a background task, this weird behavior costed me the better part of the day. But at least now I know what the problem was.


For the sake of completeness I'd mention two solutions of WPF guru Dean Chalk:

  1. Create a thread-safe observable collection. It's an old school solution that just works. To get the source code check a short article in his blog. This one was mentioned by anvarbek raupov in this thread earlier. Similar solution is in Sasha Barber's blog.
  2. Use Reactive Extensions library. See this article for an example. It's a bit bulky for one task, but meanwhile it brings a bunch of modern tools what come in handy.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜