开发者

Adding items to ObservableCollection from ThreadPool

My question is quite simple I have a class which contains a (private) object of type ObservableCollection<T> and now I'd like to run some threads (in sequence, thus the ThreadPool and not BackgroundWorkers) which add new items to the ObservableCollection<T>.

If the ObservableCollection<T> would be, let's say, a ProgressBar, all would be quite开发者_运维技巧 easy (-> Invoke) but I have no idea how to invoke the ObservableCollection<T> object.

My goal is to have something like a BackgroundWorker which can be run sequence.

Thank you in advance.


I recommend using Task objects for the background operations and queueing updates to the UI thread using TaskScheduler.FromCurrentSynchronizationContext.


Let's say you want to add a StatusItem item to an observable collection. In the .cs file of the user control, you might declare it like this:

ObservableCollection<StatusItem> _listStatus = 
       new ObservableCollection<StatusItem>();

You can then declare a method to add items like so:

private void AddStatus(StatusItem item, bool useDispatcher)
{
    if (useDispatcher) {
        Dispatcher.BeginInvoke(DispatcherPriority.Send, 
           new ThreadStart(() => AddStatus(item, false)));
        return;
    }

    if (_listStatus.Count > MaxItemsToHoldInList) {
        // maybe you have a more efficient way to do this
        for (int i = 0; i < BlockOfItems; i++ ) _listStatus.RemoveAt(0);
    }

    _listStatus.Add(item);

    if (_scrollIntoView) listStatus.ScrollIntoView(item);
}

I've taken a few liberties, so maybe you don't need all of this. Basically, if you want to call this method from inside a worker thread, you must use the dispatcher to postpone your modification until it hits the user thread (which sounds like what you want to do). You probably already figured out that if you weren't using a dispatcher thread that your updates weren't making it to the GUI. Of course, if you are actively in the user thread (responding to a mouse click, for instance), you can set useDispatcher = false when you call this method.

I personally use observable collections a lot for feedback to the user, and so, in my case, I limit the window that the user will be able to see. Removing items a bundle at a time is for performance when you are really zinging those status messages out. I also check to see if the user dropped the thumb at the bottom of the list control on which these items are shown. If they did, then I set _scrollIntoView to true to keep the bottom-most item in view.


You can safely synchronize access to the collection like this:

lock (myCollection) {
    myCollection.InsertItem(0, myItem);
}

Only one thread can modify the collection at a time. Be sure to place any code using the collection inside of the lock block.


You cannot really do this without creating your own collection class. How do I update an ObservableCollection via a worker thread?

There are some implementations of thread-safe observabler collections available : http://www.deanchalk.me.uk/post/Thread-Safe-Dispatcher-Safe-Observable-Collection-for-WPF.aspx

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜