Skip to main content

Manage Multi-Thread Data Updates

  • 4 minutes to read

When your application uses multiple threads to separate time-consuming operations from the main thread, you should synchronize access to a data source to ensure your application works correctly. You can process multi-thread data updates in one of the following ways:

Dispatch Updates to the Main Thread

Use the Dispatcher.BeginInvoke method to transfer data updates from a separate thread to the main tread.

//separate thread
Dispatcher.BeginInvoke(new Action(() => Customers.Add(new Customer { Name = "Bill" }));

The Dispatcher.BeginInvoke method executes its delegate asynchronously. In this case, data updates are delayed. You should not use this technique if you need instant data updates.

The following article lists techniques you can use to speed up data updates: Frequent Data Updates.

Wrap a Source Collection into CollectionView

Wrap your data source collection in a CollectionView and use the BindingOperations.EnableCollectionSynchronization method to synchronize access to the collection from multiple threads:

public class ViewModel {
    private object _syncLock = new Object();
    public ObservableCollection<Customer> Customers { get; set; }
    public ICollectionView Collection { get; set; }

    public ViewModel() {
        Customers = new ObservableCollection<Customer>();
        for (int i = 0; i < 50; i++) {
            Customers.Add(new Customer() { ID = i, Name = "Name" + i, IsChecked = i % 2 != 0 });
        }
        Collection = CollectionViewSource.GetDefaultView(Customers);
        BindingOperations.EnableCollectionSynchronization(Customers, _syncLock);
    }

    public void Button_Click(object sender, RoutedEventArgs e) {
        var thread = new Thread(() => {
            lock (_syncLock) {
                Customers.Add(new Customer());
            }
        });
        thread.Start();
    }
}

Refer to the following topic for more information on how to bind the GridControl to ICollectionView: Binding to ICollectionView.

Lock GridControl Updates to Synchronize Access to Data

We recommend that you perform data updates in the main thread. If you need to update data in a separate thread, lock the GridControl to synchronize access to the data collection. To do this, enclose a code block that processes updates between DataControlBase.BeginDataUpdate and DataControlBase.EndDataUpdate calls. Refer to the following topic for more information: Lock Updates.

If user actions change the GridControl’s layout (for example, scrolls the data area), the GridControl applies changes made in a separate thread after a DataControlBase.BeginDataUpdate call. The control does not sort or filter the modified rows because all data operations are locked.

View Example: Data Grid for WPF - How to Update Data in a Separate Thread

If you use the TreeListView, the GridControl processes updates according to the data structure type and might update nodes even when you lock the control. Call the TreeListView.BeginDataUpdate(bool recreateNodesOnEndDataUpdateOnly) method with the true parameter to recreate nodes only after you unlock the control. Refer to the following topic for more information: Lock Updates.

You can also dispatch data updates to the main thread.

Note

For the Self-Referential Data Structure, the TreeListView.BeginDataUpdate(bool recreateNodesOnEndDataUpdateOnly) method does not fully lock node updates and the cross-thread exception can still occur. In this case, it is necessary to dispatch data updates to the main thread.

Cross-Thread Operation Exception

We recommend that you use one of the techniques above to manage multi-thread updates correctly. If you cannot use these techniques in your application and a cross-thread operation exception occurs, you can disable the exception and push updates to the main thread. Note that this workaround does not guarantee that a control processes changes correctly.

The DXGridDataController and TreeListDataController components have the DisableThreadingProblemsDetection property. Set this property to true to disable exceptions. We marked this property obsolete because it can cause potential issues.