Issue with cross threading even when no UI elements are being updated

MattNorman

Well-known member
Joined
May 22, 2021
Messages
98
Programming Experience
1-3
I have a collection in my ViewModel which is:
C#:
public ObservableCollection<ReportAgentCallSummaryModel> ReportData { get; set; } = new ObservableCollection<ReportAgentCallSummaryModel>();

I am calling a method in a static class that takes this collection as a parameter and then uses ClosedXML to write data to a spreadsheet.

Originally I was running the export method without forcing it to run on the UI thread and it was all fine.

The view for this report has a toggle which turns the date field on/off and updates the collection.

I found that after toggling the dates on, the export method was throwing an exception (The calling method cannot access the object as it is owned by another thread).

I then changed the export method to use Application.Current.Dispatcher.Invoke to run it on the UI thread.

This resolved the issue exporting data when the ate toggle had been turned on. It however then broke the export when the toggle was not switched on.

I'm not sure how a toggle that simply reloads the collection data and unhides a data grid column can cause this issue. The collection is modified and loaded with data before the export function is called in any case.

The export methods fails at this step which is using the ClosedXML InsertTable method to write the collection to the worksheet.
C#:
var table = worksheet.Cell("B5").InsertTable(reportData);

It's not clear if the exception definitely relates to the collection that is being passed or if it's the worksheet object itself.

In either case, the worksheet object is currently being created on the UI thread along with the rest of the export method.

I have also tried making a new copy of the collection that is not bound to any controls and passing that however it did not make any diffrence.
 
I'm not sure how a toggle that simply reloads the collection data and unhides a data grid column can cause this issue.

Is a DataGrid not a UI element? You should not be doing anything to the UI on any but the UI thread. That may or may not be your issue though. You're suing an ObservableCollection so I'm guessing that it's bound to a control. If you reload that collection, that bound control must be updated to reflect the new data and that can only be done on the UI thread.
 
Yes the DataGrid is a UI element and the ReportData collection is bound to it.

I have removed the use of any additional Threads/Tasks to try and rule things out.

Oddly now, if I load the report data in to the collection and update the UI and then try to export, it fails with the same error.

If I load the report, toggle the data field on and then back off the exports works fine.

All the toggle is doing is updating the backing field value datesEnabled, updating a property for the Date column visibility and then loading data in to the collection again.

I can't how enabling the dates and disabling it again seems to make it work.
 
I've done away with the InsertTable method from ClosedXML and switched to a loop and manually adding the table data. The issue no longer occurs.

There seems to be some element of that method crossing threads even though it should not be modifying the source collection.

It was also showing strange behaviour in that sometimes the order of columns would be different for no reason.
 
Back
Top Bottom