3

I have a basic WPF-Application.It contains a Datagrid that is bound to a AsyncObservableCollection . When adding items to the Collection from a different thread then i'm getting the following exception at Random.

An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll

Additional information: An ItemsControl is inconsistent with its items source.

"Information for developers (use Text Visualizer to read this):\r\nThis 

    exception was thrown because the generator for control 
    'System.Windows.Controls.DataGrid Items.Count:3' with name 'logPanel' has received sequence of CollectionChanged events that do not agree with the current state of the Items collection.  The following differences were detected:\r
Accumulated count 1 is different from actual count 3.  [Accumulated count is (Count at last Reset + #Adds - #Removes since last Reset).]\r
\n  At index 0:  Generator's item 'BorgingIskMainApp.Model.LogItem' is different from actual item 'BorgingIskMainApp.Model.LogItem'.

Some code:

Note: myLogItems is the AsyncObservableCollection

The Binding

    public MainWindow()
    {
        myLogItems = new AsyncObservableCollection<LogItem>();
        logPanel.ItemsSource = myLogItems;
    }

Initialization of the Task

    System.Windows.Application.Current.Dispatcher.BeginInvoke(
    System.Windows.Threading.DispatcherPriority.Normal,(Action)delegate()
    {
        DocumentTest cg = new DocumentTest();
        Task.Factory.StartNew(() => { cg.PerformWVSTest(myLogItems); });
    });

My Method

    public void PerformWVSTest(ObservableCollection<LogItem> dgResults)
    {
        try
        {

            dgResults.Insert(0,lgItem.CreateNewLogItem(dgResults.Count, "Start WVS-Test", true));
         ....
        }
    }

My Object

public class LogItem
{

    public LogItem() {
        logId = 0;
        logText = String.Empty;
        isSuccess = true;
    }
    public Int32 logId { get; set; }
    public String logText { get; set; }

    public Boolean isSuccess { get; set; }

    public LogItem CreateNewLogItem(Int32 pLogId, String pLogText, Boolean success)
    {
        ADF.Diagnostics.TextFileTracer.Write(pLogText);
        return new LogItem { logId = pLogId, logText = pLogText, isSuccess = success };
    }
}

Anyone got an idea what might cause this exception?

Note: The exception can occur at any moment. There is no stated time or index where it Always happens

Note 2: Code of AsyncObservableCollection

public class AsyncObservableCollection<T> : ObservableCollection<T>
    {
        private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;

        public AsyncObservableCollection()
        {
        }

        public AsyncObservableCollection(IEnumerable<T> list)
            : base(list)
        {
        }

        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (SynchronizationContext.Current == _synchronizationContext)
            {
                // Execute the CollectionChanged event on the current thread
                RaiseCollectionChanged(e);
            }
            else
            {
                // Raises the CollectionChanged event on the creator thread
                _synchronizationContext.Send(RaiseCollectionChanged, e);
            }
        }

        private void RaiseCollectionChanged(object param)
        {
            // We are in the creator thread, call the base implementation directly
            base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
        }

        protected override void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (SynchronizationContext.Current == _synchronizationContext)
            {
                // Execute the PropertyChanged event on the current thread
                RaisePropertyChanged(e);
            }
            else
            {
                // Raises the PropertyChanged event on the creator thread
                _synchronizationContext.Send(RaisePropertyChanged, e);
            }
        }

        private void RaisePropertyChanged(object param)
        {
            // We are in the creator thread, call the base implementation directly
            base.OnPropertyChanged((PropertyChangedEventArgs)param);
        }
    }

Source for AsyncCollection: wpf-binding-to-an-asynchronous-collection

All credit to the designer of the object!

User999999
  • 2,500
  • 7
  • 37
  • 63
  • Did you try using Dispatcher instead of SynchronizationContext? – Yegor Jun 02 '15 at 14:07
  • @Yegor, not yet. But its a alternative worth looking into. But isn't `SynchronizationContext` just a generic wrapper around `Dispatcher`? – User999999 Jun 02 '15 at 14:12
  • 1
    People [say](http://stackoverflow.com/a/2050346/141045) it may be not. – Yegor Jun 02 '15 at 14:16
  • @Yegor: Interesting post!!! must have missed that one. I'll try using a Dispatcher instead of SynchronizationContext. Lets hope for success :) – User999999 Jun 02 '15 at 14:23

0 Answers0