manuel
Topic Author
Posts: 13
Joined: 16 Aug 2022, 10:06

Feed a ViewModel with massive Data coming from a different Thread

14 Feb 2023, 12:16

Hey everyone,

we've set up Noesis in a way that it lives on its own thread. Nevertheless, the data it has to display comes from a different thread. So, how can we access the data without locking the database for a long time? Executing the OnPropertyChanged event for hundreds of elements in a ViewModel and refreshing the layout will take its time.

My naive attempt is to implement a queue between the threads that swaps out multiple versions of the ViewModel:
So the database accesses and writes to ViewModel A. When an update is finished, ViewModel A gets swapped with ViewModel B, and the database thread can already release the lock, freeing up the thread to continue its duty. In the meanwhile, the UI-thread can execute all the layout work and OnPropertyChanged events with the data it got.

In practice, I am not sure what Noesis' reflection system has to say about the fact that its underlying ViewModel is exchanged all the time. But I fear that it is not doable. To implement the OnPropertyChanged event in the first place, I need to derive from Noesis::BaseComponent. But BaseComponent has its copy-constructor explicitly deleted. Therefore, I cannot execute std::swap on such a ViewModel. Which prevents me to implement a queue with the ViewModel itself.

Leaving me with the questions:
- Am I right in the assumption that I cannot swap a registered ViewModel?
- What would your approach be in such a situation?
 
User avatar
jsantos
Site Admin
Posts: 3747
Joined: 20 Jan 2012, 17:18
Contact:

Re: Feed a ViewModel with massive Data coming from a different Thread

16 Feb 2023, 02:21

Hi Manuel,

As far as I understand, you can swap the viewmodel by setting the new pointer calling SetDataContext. BaseComponent cannot be copied but that's on purpose.

So I think, the scenario you describe can be resolved as:

1. Install an initial Viewmodel in the UI thread.
2. Fill a new ViewModel in a custom thread (note, do not invoke NotifyPropertyChanged here)
3. When this the new ViewModel is filled and ready, just enqueue it to the UI thread
4. In the UI thread, set the new ViewModel (by calling SetDataContext), this call will rebind the whole model.

Please, let me know if this makes sense to you.
 
manuel
Topic Author
Posts: 13
Joined: 16 Aug 2022, 10:06

Re: Feed a ViewModel with massive Data coming from a different Thread

24 Feb 2023, 18:04

Thanks for the answer and yes, I could follow your instructions. I got a proof of concept to run but had some issues with it. It was no problem to exchange the ViewModels via SetDataContext while the data was shown in a TreeView. But whenever I selected an entry to display additional data about a given entry in another UIElement, the game crashes after some more cycles of exchanging the ViewModel. For some reason, a Pointer got invalid all the time...

In the end, I changed the system's architecture. Instead of exchanging the entire ViewModel all the time, I set up a system that only passes individual sets of data from one thread to the other.
So the UIThread raises a "DataRequest" event that gets processed by the DataBaseThread. When the data has been collected, the DataBaseThread pushes the data into a DataQueue. The UIThread observes this DataQueue, identifies the ViewModel the data belongs to, and the ViewModel starts updating itself according to the new data set.

The main benefit here is that my DataBaseThread does not need to know much about Noesis API. The entire data processing, like type conversions, is done on the UIThread as well. And I can be very selective with what elements of a ViewModel I want to update.
 
User avatar
jsantos
Site Admin
Posts: 3747
Joined: 20 Jan 2012, 17:18
Contact:

Re: Feed a ViewModel with massive Data coming from a different Thread

01 Mar 2023, 10:45

But whenever I selected an entry to display additional data about a given entry in another UIElement, the game crashes after some more cycles of exchanging the ViewModel. For some reason, a Pointer got invalid all the time...
Do you have a mini-dump for this crash? I would like to have a look at it.
The main benefit here is that my DataBaseThread does not need to know much about Noesis API. The entire data processing, like type conversions, is done on the UIThread as well. And I can be very selective with what elements of a ViewModel I want to update.
This implementation is much better than the original proposal. Glad to know you found a way to properly implement this. :)

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 1 guest