i am making an application in silverlight 3.0. In that application i have one public method as
public void DrawWavform()
{
Line[,] line = new Line[10,200];
line[i,j]= new Line();//i am getting error here of invalid thread access
//some operation
}
In application i am creating different threads as per user inputs and calling DrawWaveform method from that newly created thread. I want to parallel opeation.Please suggest me solution.Thanks in advance.
Any operation changing the GUI must be executed on the UI thread. This can be done using the dispatcher:
Deployment.Current.Dispatcher.BeginInvoke( () =>
{
// update ui
});
or
(SomeDependencyObject).Dispatcher.BeginInvoke( () => { /* ... */ } );
Anyway, this code should be used very rarely and contain only UI related code. Executing expensive operations on the UI thread will cause your application to hang.
Related
What is the recommended way to do multithreading with MVVM Light.
I have a model which has a bool property Busy
public bool Busy
{
get { return busy_; }
set
{
Set(nameof(Busy), ref busy_, value, broadcast: true);
}
}
My view model publish the model directly for the view (the model is inherit MVVM Light's ViewModelBase), so the view binds directly to the model's busy property.
If I call the model always from the UI thread everything is good. But if I do the following in my view model so it may execute on a different thread
Task.Factory.StartNew(() =>
{
model_.SomeFunctionThatWillSetBusyDuringItsExecution();
});
Then of course Busy is set from a non UI thread and then the binding fails and the application crashes. If I happen to use the Messenger in the property setter, it seems the Messenger does not automatically dispatch the Messenger handler code to the UI thread either.
I realized there is a DispatcherHelper in MVVM Light, but for the binding it does not seem to help. If I change the property to
public bool Busy
{
get { return busy_; }
set
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
Set(nameof(Busy), ref busy_, value, broadcast: true);
});
}
}
I still get an exception and the application crash due to the binding source is not on the correct thread. So my question is simple, what is the recommended way to do multithreading like this in MVVM Light?
I did also try to use a syncronizationContext.
syncContext_.Post(() =>
{
Set(nameof(Busy), ref busy_, value, broadcast: true);
}, null);
That works if the call is always from a non UI-thread. If the call is already from the UI thread, the syncContext.Post results in that the Set() function is not called until all the code in the ViewModel method has finished. That means the busy state might not be updated correctly for the remaining code. So it is not an ideal solution.
I am thankful for help on this topic.
Instead of adding the DispatcherHelper code inside the property I added it at all places where the property was modified. Then it seems to work well.
Only problem, since one dispatch the work to the UI thread, the code in the ViewModel would not get the updated state if part of the view model method already runs on the UI thread. I found a way to force the UI thread to process its messenger queue though making sure it got the updated state of Busy. It is not the best looking solution, and it is likely to have a bad performance impact due to all context switching, but at least it works and it is a simple one liner.
Code to force the UI thread to process all messages in its queue
DispatcherHelper.UIDispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);
If there is a more optimal way to solve it then please let me know. Otherwise I will set this as the answer in a few days from now.
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.
I am trying to make a stopwatch in Xamarin Forms and was wondering if I should use the native UI threading or Parallel Task Lib to constantly update the time label?
I tried to use the PT Lib, but I'm unable to get it to update my label, which makes me think that I should be using Native Threading, but I'm worry if I would be able to update the UI using a dependency service.
Is there a best practice for constantly updating the UI but still being able to execute other tasks such as button clicks?
UPDATE: I got this code below to work, but is this good practice? I am updating the time label constantly while still also bing able to press the lap buttons.
Stopwatch sw = new StopWatch();
bool inRace = false;
async void StartLapClick(object sender, System.EventArgs e)
{
if (!inRace)
{
inRace = true;
sw.Start();
updateTimer();
}
}
async void updateTimer()
{
await Task.Run(() =>
{
while(inRace)
{
string slc = sw.Elapsed.ToString();
Device.BeginInvokeOnMainThread(() =>
{
timerLbl.Text = slc;
});
Task.Delay(100).Wait();
}
});
}
No, your code has some issues (according to the Best Practices in Asynchronous Programming):
async void is bad - this will call your method in fire-and-forget fashion, you even can't get the errors from there. You should use it only for event handlers like StartLapClick, not for real methods like updateTimer
Task.Delay(100).Wait(); - Do not block on tasks, use await for this
replace the whole while loop with a simple timer, and remove the Task.Delay call
updateTimer(); - you're calling async method in synchronous fashion, which is also bad.
You have to update the UI from the UI thread. You could have a timer or something running in the background kicking out events periodically to be picked up and forwarded to the UI thread. Even if you did that, I don't know that the parallel task library is what you'd want to use. That's more focused on running many tasks... in parallel.
Try this:
Device.StartTimer(TimeSpan.FromSeconds(1.0), () => {
// Your code
};
I am developing an AIR application for iOS/ Android and I am using a backend service for database operations. The backend service provides asynchronous API's for loading and saving the data. I happen to stumble at a piece of logic which caught my attention:
Main
public funciton loadPlayerData():void
{
service.loadData();
// Busy lock
while( !service.client == true );
// Do some stuff after the client is received
}
Service
public function loadData()
{
// Call the external service and specify success callback as
// onSuccess
}
public function onSuccess():void
{
this.client = true;
}
public var client:Boolean = false;
What I am trying to do in the above code is that I am calling an async operation on service and while it is fetching data from server, I am busy spinning waiting for the client to set true in the callback. According to my understanding, this is how locking is done for resources in operating system and all. ( Though there are more elegant solutions in operating system other than busy wait ).
But the results are such that the Main gets stuck in an infinite busy waiting implying that onSuccess never gets called. The reason, according to my understanding is that until and unless the the current execution ends ( or when the stack of current execution is completely popped out), control is not given to the callback Function and hence my implementation results in never ending spin wheel. My basic assumption that thread is multiplexed from time point of view is flawed and thats the explanation I can deduce from the premise.
I want to know whats the actual reason behind the above scenario? How far I am correct in my deduction and what are the details behind execution of actionscript code in scenario like these ?
The AS3 runtime is not multithreaded - your script runs on a single thread with certain operations internally running on a separate thread (like network calls, etc.) The only way to properly handle your situation is to split up your work into multiple steps; you then initiate the first step (calling the remote service) and pass a callback function. There's no need to wait in a loop (in fact, it hurts you as you discovered) - when the network call is done, your callback will be called and you can initiate the next step of your processing. Until this 2nd step is called, the rest of your program should assume that the data from the remote service is not available.
Your code would be something like:
public funciton loadPlayerData():void
{
service.loadData();
// Nothing else here - you must wait for the data
// to be avaiable.
}
public function loadData()
{
// Call the external service and specify success callback as
// onSuccess
}
public function onSuccess():void
{
// Call logic that performs "Do some stuff
// after the client is received" from your
// question.
}
I think this should solve the issue, depending on how you determine that onSuccess is called (I assume its a function for an Event Listener.)
First off, your Service class needs to inherit EventDispatcher, either directly or indirectly, so that you gain access to dispatchEvent(event) function.
Main
public funciton loadPlayerData():void
{
service.loadData();
service.addEventListener(Event.COMPLETE, onServiceLoadedData);
}
private function onServiceLoadedData(e:Event):void{
...
}
Service
...
public function onSuccess():void
{
//after everything has been loaded
dispatchEvent(new Event(Event.COMPLETE));
}
As a side note, if you need to access stuff from your Service class and you don't want to handle it through setter/getter variables and such like, you can make a custom Event and pass all the necessary Information there.
today I've added multi threading to a windows forms application. On my UI thread I'm starting a thread via new Thread() {...}).Start(); Which itself will call a Method which uses ThreadPool.QueueUserWorkItem(). After the Method is called the thread will wait on a queue until a specific item is returned and the thread exits:
new Thread(o =>
{
s.SimulateChanges();
Boolean run = true;
while (run)
{
SimulationResult sr = queue.WaitDequeue();
//EOF is a static property which will be returned
//if the queue is at its end so I can break the while loop
if (SimulationResult.EOF.Equals(sr))
{
run = false;
continue;
}
this.simulationProgressBar.BeginInvoke((Action)delegate()
{
if (sr.IsDummy && this.simulationProgressBar.Value < this.simulationProgressBar.Maximum)
{
/*...*/
}
else
{
this.resultListView.AddObject(sr);
}
});
}
this.simulationProgressBar.BeginInvoke((Action)delegate()
{
this.ToggleSimulationControls(true);
});
}).Start();
And that is the code of the method called:
public void SimulateChanges()
{
ThreadPool.QueueUserWorkItem(o =>
{
foreach (IColElem elem in collection.AsEnumerable())
{
/*lot of code*/
queue.Enqueue(new SimulationResult() { IsDummy = true });
}
log.Debug("Finished!");
queue.Enqueue(SimulationResult.EOF);
});
}
My Queue is a self written class allowing a thread to wait on dequeue until an object ins enqueued.
Everything is working fine, except that if I stop debugging (using stop debugging or simply closing the application) I can't rebuild my application as VS2010 doesn't remove the file handle. I believe it has something to do with my threads not exiting correctly. Is their any way I can assure this?
Thanks for any advice :-)
Hard to explain all aspects of the question. But you are making a pretty common mistake, often made by programmers when they first start using threads. You are not making sure that the thread stops running when the user closes the main window. It is an easy mistake to make, the UI thread takes care of a lot of grunt work. Including automatically terminating when the main window of your app is closed by the user. So at least part of your problem is that you did manage to close the main window. But didn't actually terminate the process. Building cannot work, your program's EXE is still in use.
Properly shutting down a thread can be very difficult, given that the user will close the window regardless of what that thread is doing. It could be catatonic, buried deep inside an operating system call and waiting for it to complete. Tough to ask it to quit when it isn't executing code.
There is a very simple solution, at least good enough to keep going with your project or solve half the problem you have. You can mark the thread as "kill automatically at program termination" and the CLR will take care of it. Use the IsBackground property, like this:
var t = new Thread(o =>
{
// Lotsa code
});
t.IsBackground = true;
t.Start();
But do keep in mind that there's nothing graceful about that kind of kill. If you are writing a file or talking to a server then that's going to cause a partially written file or a very confused server. Otherwise not different from killing the program with task manager.