How to create an observableCollection Sortable and multithreading - multithreading

Here is my problem , I have created a SortableCollection : ObservableCollection
and added a sort method (sort colors).
When I sort The collection with the principal Thread , it works every thing is fine and works
But When I try to sort this customCollection by using an item in the collection I have an expetion : (The calling thread cannot access this object because a different thread owns it).
I have looked in web and I found several solution , One Solution
This type of solution put the collection multithread for insertion , removing moving operation.
But not for the custom sort.
Thanks for help,

WPF classes have thread affinity. What this means is that all changes to those objects must be in the same thread where they were created. It truly is difficult to create a user interface API that is thread-safe, so Microsoft chose to keep it singlethreaded and force run-time checking to make sure of it.
That said, there are a few options you have to perform your sort in a background thread, and then apply it in the UI thread. The first option is to copy your SortableCollection into a plain old List or Array and perform the sort in the background. Once the background thread is complete, you use a Dispatcher to execute code in the UI thread. Every UI element in WPF extends System.Windows.Threading.DispatcherObject and most extend System.Windows.Freezable. The DispatcherObject is where you get the Dispatcher to execute code in the UI thread.
Logically, the execution would be something like this:
public void BackgroundSort()
{
List<T> items = new List<T>(this.ToArray());
BackgroundSortDelegate del = Sort;
del.BeginInvoke(SortCompleted, del);
}
private void SortCompleted(IAsyncResult result)
{
BackgroundSortDelegate del = result.AsyncState as BackgroundSortDelegate;
List<T> items = del.EndInvoke(result);
this.Dispatcher.Invoke(()=>{this.Collection = items;});
}
The short explanation of what happened is that the background worker/delegate is using a copy of the items in this list. Once the sort is complete, we are calling the Dispatcher object and invoking an action. In that action we are assigning the new sorted list back to our object.
The key to assigning the result of any background work within the UI thread is to use the UI's Dispatcher object. There's actually probably a half dozen ways to invoke a background worker in C#, but the approach to get your work in a background thread into the UI thread is the same.

Related

What is Device.BeginInvokeOnMainThread for?

I would like someone to explain to me what is Device.BeginInvokeOnMainThread and what is it for?
And also some examples of cases where it's used.
Just to add an example.
Imagine you have an async method DoAnyWorkAsync if you call it (just as an example) this way:
DoAnyWorkAsync().ContinueWith ((arg) => {
StatusLabel.Text = "Async operation completed...";
});
StatusLabel is a label you have in the XAML.
The code above will not show the message in the label once the async operation had finished, because the callback is in another thread different than the UI thread and because of that it cannot modify the UI.
If the same code you update it a bit, just enclosing the StatusLabel text update within Device.BeginInvokeOnMainThread like this:
DoAnyWorkAsync().ContinueWith ((arg) => {
Device.BeginInvokeOnMainThread (() => {
StatusLabel.Text = "Async operation completed...";
});
});
there will not be any problem.
Try it yourself, replacing DoAnyWorkAsync() with Task.Delay(2000).
The simple answer is: Background thread cannot modify UI elements because most UI operations in iOS and Android are not thread-safe; therefore, you need to invoke UI thread to execute the code that modifies UI such MyLabel.Text="New Text".
The detailed answer can be found in Xamarin document:
For iOS:
IOSPlatformServices.BeginInvokeOnMainThread() Method simply calls NSRunLoop.Main.BeginInvokeOnMainThread
public void BeginInvokeOnMainThread(Action action)
{
NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}
https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/
You use this method from a thread to invoke the code in the specified object that is exposed with the specified selector in the UI thread. This is required for most operations that affect UIKit or AppKit as neither one of those APIs is thread safe.
The code is executed when the main thread goes back to its main loop for processing events.
For Android:
Many People think on Xamarin.Android BeginInvokeOnMainThread() method use Activity.runOnUiThread(), BUT this is NOT the case, and there is a difference between using runOnUiThread() and Handler.Post():
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
} else {
action.run();//<--action is executed immediately if current running thread is UI thread.
}
}
The actual implementation of Xamarin.Android BeginInvokeOnMainThread() method can be found in AndroidPlatformServices.cs class
public void BeginInvokeOnMainThread(Action action)
{
if (s_handler == null || s_handler.Looper != Looper.MainLooper)
{
s_handler = new Handler(Looper.MainLooper);
}
s_handler.Post(action);
}
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
As you can see, you action code is not executed immediately by Handler.Post(action). It is added to the Looper's message queue, and is handled when the UI thread's scheduled to handle its message.
You can only update the UI from the main UI thread. If you are running code on a background thread and need to update the UI, BeginInvokeOnMainThread() allows you to force your code to run on the main thread, so you can update the UI.
As explained above, any UI updates must happen in the main thread or an exception will occur.
Though there's a peculiarity with Xamarin.Forms, one can manilpulate UI elements (e.g. create Labels and add them to StackLayout's Children collection) off the main thread without any failures as long as this part of UI is detached from UI elements currently displayed. This approach can be used to boost performance by creating Xamarin.Forms controls and setting their child/parent relations in-memory/off-screen in a separate thread BUT in order to attach them to displayed container (e.g. assign ContentPage's Content property) you will have to do this in Device.BeginInvokeOnMainThread().
While analysing the relationship between UI thread and background thread in some situation, we should be aware of the following:
BeginInvokeOnMainThread method as described in the docs, merely queues the invocation and returns immediately to the caller. So in this case, UI thread and background thread which submitted some work to UI thread, might work in parallel.
However, there is also InvokeOnMainThread which, as described in the docs, waits for the UI thread to execute the method, and does not return until the code pointed by action has completed. So in this case, background thread waits for UI thread to finish executing the given work, and then background thread continues execution.

Portable Class Library and ObservableCollection, updating UI Thread

I'm not very experienced with this topic so forgive me if this isn't very clear.
I've created a Portable Class Library that has an ObservableCollection of Sections, and each secion has an ObservableCollection of Items.
Both of these collections are bound to the UI of separate Win8 and WP8 apps.
I'm trying to figure out the correct way to populate these collections correctly so that the UI gets updated from the PCL class.
If the class was inside the win8 project I know I could do something like Dispatcher.BeginInvoke, but this doesn't translate to the PCL, nor would I be able to reuse that in the WP8 project.
In this thread (Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync) I discovered the SynchroniationContext class.
I passed in a reference to the main app's SynchroniationContext, and when I populate the sections I can do so because it's only the one object being updated:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
UpdateSections(sections);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post(UpdateSections, sections);
}
However, when I try to do the same thing with articles, I have to have a reference to both the section AND the article, but the Post method only allows me to pass in a single object.
I attempted to use a lambda expression:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
section.Items.Add(item);
}, null);
}
but I'm guessing this is not correct as I'm getting an error about being "marshalled for a different thread".
So where am I going wrong here? how can I update both collections correctly from the PCL so that both apps can also update their UI?
many thanks!
Hard to say without seeing the rest of the code but I doubt is has anything to do with Portable Class Libraries. It would be good to see the details about the exception (type, message and stack trace).
The way you call Post() with more than argument looks correct. What happens if you remove the if check and simply always go through SynchronizationContext.Post()?
BTW: I don't explicitly pass in the SynchronizationContext. I assume that the ViewModel is created on the UI Thread. This allows me to capture it like this:
public class MyViewModel
{
private SynchronizationContext _context = SynchronizationContext.Current;
}
I would recommend that at least in your ViewModels, all publicly observable state changes (ie property change notifications and modifications to ObservableCollections) happen on the UI thread. I’d recommend doing the same thing with your model state changes, but it might make sense to let them make changes on different threads and marshal those changes to the UI thread in your ViewModels.
To do this, of course, you need to be able to switch to the UI thread in portable code. If SynchronizationContext isn’t working for you, then just create your own abstraction for the dispatcher (ie IRunOnUIThread).
The reason you were getting the "marshalled on a different thread" error is that you weren't passing the item to add to the list as the "state" object on the Post(action, state) method.
Your code should look like this:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
var item = (YourItemnType) e;
section.Items.Add(item);
}, item);
}
If you make that change, your code will work fine from a PCL.

QML: running functions in parallel threads

In my code I'm creating 16x16 buttons in cycle and this take few seconds.
onCreateField:
{
for(var i=0;i<fieldWidth;i++)
{
for(var j=0;j<fieldHeight;j++)
{
createButton(i, j);
}
}
}
function createButton(x, y)
{
__buttonX = x;
__buttonY = y;
__component = Qt.createComponent("GameButton.qml");
if(__component != null)
continueButtonCreation();
else
__component.ready.connect(continueButtonCreation);
}
function continueButtonCreation()
{
var button = __component.createObject(field, {"row": __buttonY, "column": __buttonX});
if (button == null) {
// Error Handling
console.log("Error creating object");
return;
}
updateValveState.connect(button.stateUpdated);
button.buttonClicked.connect(buttonClicked);
field.clearField.connect(button.release);
}
While function that creating buttons runs, app freezes. I want to show loading animation while this function runs. So, how to run this function in parallel thread to avoid freezing?
To do work in threads you have two possible approaches :
Read about the WorkerScript element. It allows you to perform certain operation by running the javascript functions as threads.
Note: As given in the documentation, there is a restriction though :
Since the WorkerScript.onMessage() function is run in a separate
thread, the JavaScript file is evaluated in a context separate from
the main QML engine. This means that unlike an ordinary JavaScript
file that is imported into QML, the script.js in the above example
cannot access the properties, methods or other attributes of the QML
item, nor can it access any context properties set on the QML object
through QDeclarativeContext. Additionally, there are restrictions on
the types of values that can be passed to and from the worker script.
See the sendMessage() documentation for details.
Just see, if for your particular use case it suits the requirement.
2
. Implement the functionality which are heavy as C++ threads. Whenever required, generate a signal to start this thread on the C++ side. When done, pass back the data from C++ to Qml , if required.
As you may or may not have determined in other posts you cannot load QML objects in javascript in parallel. Depending on your circumstances you should probably be using a GridView with a Delegate that renders a button. This allows the underlying code to efficently render the buttons instead of sequentially creating them in javascript.
Other options to not block the UI might be
use incubateObject instead of createObject
don't create all Buttons within a single (16ms) frame: use a Timer to spread the creation of the Buttons over multiple frames

How do update the UI in a generic way from other threads/delegates?

I have created psedo code of what I would like to achieve. Inside of the SomeBLL().PerformBeginWork() threads will be created and maintained to do work. Using dot.net 4.0, what would be the best way to put this processing into an non-UI thread and still allow the assigned delegates to fire and update the UI in both a windows and web application without code modifications?
public class SomeBLL : BaseAsynWorker, IAsyncWorker
{
...makes threads and does work (if events are assigned then call them)
}
On a web page
SomeBLL sm=new SomeBLL();
sm.OnBeginWork+=ProcessUIUpdate;
sm.OnProgressUpdate+=ProcessUIUpdate;
sm.OnEndWork+=ProcessUIUpdate;
sm.OnHardError+=ProcessHardError;
SomeThreadClass.Spawn(sm.PerformBeginWork())
In a non UI process
SomeBLL sm=new SomeBLL();
sm.PerformBeginWork();
You're looking for the SynchronizationContext class.

Calling QAxWidget method outside of the GUI thread

I'm beginning to wonder if this is impossible, but I thought I'd ask in case there's a clever way to get around the problems I'm having.
I have a Qt application that uses an ActiveX control. The control is held by a QAxWidget, and the QAxWidget itself is contained within another QWidget (I needed to add additional signals/slots to the widget, and I couldn't just subclass QAxWidget because the class doesn't permit that). When I need to interact with the ActiveX control, I call a method of the QWidget, which in turn calls the dynamicCall method of the QAxWidget in order to invoke the appropriate method of the ActiveX control. All of that is working fine.
However, one method of the ActiveX control takes several seconds to return. When I call this method, my entire GUI locks up for a few seconds until the method returns. This is undesirable. I'd like the ActiveX control to go off and do its processing by itself and come back to me when it's done without locking up the Qt GUI.
I've tried a few things without success:
Creating a new QThread and calling QAxWidget::dynamicCall from the new thread
Connecting a signal to the appropriate slot method of the QAxWidget and calling the method using signals/slots instead of using dynamicCall
Calling QAxWidget::dynamicCall using QtConcurrent::run
Nothing seems to affect the behavior. No matter how or where I use dynamicCall (or trigger the appropriate slot of the QAxWidget), the GUI locks until the ActiveX control completes its operation.
Is there any way to detach this ActiveX processing from the Qt GUI thread so that the GUI doesn't lock up while the ActiveX control is running a method? Is there something clever I can do with QAxBase or QAxObject to get my desired results?
After some experimentation, I was able to solve this by doing something I thought I'd tried earlier: creating a new QThread and calling QAxWidget::dynamicCall from the new thread. I must not have coded it correctly the first time I tried this solution; after sitting with a co-worker, we were able to get it to work. To be specific, what we did is:
(Step 1) Created a subclass of QThread to represent the thread I need to call dynamicCall().
(Step 2) In the constructor of my QThread, pass in a pointer to my original QAxWidget, and keep the pointer in a member variable.
MyThread::MyThread(QAxWidget* passedWidget) : QThread()
{
actualWidget = passedWidget;
}
(Step 3) In the run() method of the QThread, call the dynamicCall() method of the QAxWidget.
void MyThread::run()
{
QVariant result = actualWidget->dynamicCall(...parms as necessary...);
}
(Step 4) Back in my main code, when I need to execute dynamicCall(), I just call the start() method of MyThread. The start() method will execute run() in its own thread, thus sending the necessary command to the ActiveX object without blocking or stalling the main GUI thread.
If there is no event loop needed, then there is no need NOT to subclass QThread! I think this is the way to solve this without a bunch of signals to the main thread which (more than likely) owns the QAxWidget. The latest docs for Qt 5.3 referring to QThread also bears this out.

Resources