Cross Thread UI - multithreading

I have an issue with cross threading on a UI. I have read all the ways to do it and have implemented them as seen below.
public void UpdateList(object obj)
{
// do we need to switch threads?
if (listBox1.InvokeRequired)
{
MethodInvoker del = () => UpdateList(obj);
this.Invoke(del);
return;
}
// ok so now we're here, this means we're able to update the control
// so we unbox the object into a string
string text = (string)obj;
// and update
listBox1.Items.Add(text);
}
The issue comes when I try to do a
hubConnection.Start().Wait();
After that call I am trying to update my list.
Without the wait is fine. When I add the Wait it hangs on the UpdateList Invoke. There is no error...it just hangs.
I am handling this call in a button event.

Wait() is creating a deadlock on the mainthread.
Replace the hubconnection.Start.Wait() with:
await hubconnection.Start() in an async method:
public void async StartHubClickedEvent(...){
await hubconnection.Start()
}
The Microsoft Async library enables use of async/awaut on .net 4.0 and VS12.
Install-Package Microsoft.Bcl.Async
See Deadlock when thread uses dispatcher and the main thread is waiting for thread to finish

You've generated a recursive loop. Assuming an Invoke is Required, you'll call up the same method, hit if (listBox1.InvokeRequired) again (which will still pass true) and start looping as you keep calling up the same method again and again. It's better to do an If..Else pattern here where you directly invoke the change on the ListBox or simply perform the change without the invoke
An Example
if (listBox1.InvokeRequired)
{
listBox1.Invoke(()=> { listBox1.Items.Add((string)text) };
}
else
{
string text = (string)obj;
// and update
listBox1.Items.Add(text);
}

Related

Kotlin: Why isn't job.invokeOnCompletion() block running on main thread?

In my Android application I have code that should run periodically in its own coroutine and should be cancelable.
for this I have the following functions:
startJob(): Initializes the job, sets up invokeOnCompletion() and starts the work loop in the respective scope
private fun startJob() {
if (::myJob.isInitialized && myJob.isActive) {
return
}
myJob= Job()
myJob.invokeOnCompletion {
it?.message.let {
var msg = it
if (msg.isNullOrBlank()) {
msg = "Job stopped. Reason unknown"
}
myJobCompleted(msg)
}
}
CoroutineScope(Dispatchers.IO + myJob).launch {
workloop()
}
}
workloop(): The main work loop. Do some work in a loop with a set delay in each iteration:
private suspend fun workloop() {
while (true) {
// doing some stuff here
delay(setDelayInMilliseconds)
}
}
myJobCompleted: do some finalizing. For now simply log a message for testing.
private fun myJobCompleted(msg: String) {
try {
mainActivityReference.logToGUI(msg)
}
catch (e:Exception){
println("debug: " + e.message)
}
}
Running this and calling myJob.Cancel() will throw the following exception in myJobCompleted():
debug: Only the original thread that created a view hierarchy can touch its views.
I'm curious as to why this code isn't running on the main thread, since startJob() IS called from the main thread?
Furthermore: is there a option similar to using a CancellationTokenSource in c#, where the job is not immediately cancelled, but a cancellation request can be checked each iteration of the while loop?
Immediately breaking off the job, regardless of what it is doing (although it will pretty much always be waiting for the delay on cancellation) doesn't seem like a good idea to me.
It is not the contract of Job.invokeOnCompletion to run on the same thread where Job is created. Moreover, such a contract would be impossible to implement.
You can't expect an arbitrary piece of code to run on an arbitrary thread, just because there was some earlier method invocation on that thread. The ability of the Android main GUI thread to execute code submitted from the outside is special, and involves the existence a top-level event loop.
In the world of coroutines, what controls thread assignment is the coroutine context, while clearly you are outside of any context when creating the job. So the way to fix it is to explicitly launch(Dispatchers.Main) a coroutine from within invokeOnCompletion.
About you question on cancellation, you can use withContext(NonCancellable) to surround the part of code you want to protect from cancellation.

Without AsyncTask, running a thread in background and updating the UI Thread

I was trying to update the recycler view content from a background thread in Kotlin. I am not using AsyncTask.
Here is my code, i want to know if there is any better way than this:
In my MainActivity, i have progressThread as a member variable.
var progressThread = Thread()
Then in my method where i want to run the thread first i am defining it...like
progressThread = Thread (
Runnable {
kotlin.run {
try {
while (i <= 100 && !progressThread.isInterrupted) {
Thread.sleep(200)
//Some Logic
runOnUiThread {
//this runs in ui thread
}
i++
}
}catch (e:InterruptedException){
progressThread.interrupt()
}
}
})
after that i am starting it in the same method as
progressThread.start()
and for stopping it, i have a listener to cancel the progress and in the callback of that listener, i have written:
progressThread.interrupt()
Updated
Coroutines are stable now,: https://kotlinlang.org/docs/reference/coroutines-overview.html
Old Answer
Yes, you can do this using doAsync from kotlin anko library that is fairly simple and easy to use.
add following line in module level gradle file:
compile "org.jetbrains.anko:anko-commons:0.10.0"
Code example:
val future = doAsync {
// do your background thread task
result = someTask()
uiThread {
// use result here if you want to update ui
updateUI(result)
}
}
code block written in uiThread will only be executed if your Activity or Fragment is in foreground mode (It is lifecycle aware). So if you are trying to stop thread because you don't want your ui code to execute when Activity is in background, then this is an ideal case for you.
As you can check doAsync returns a Future object so you can cancel the background task, by cancel() function:
future.cancel(true)
pass true if you want to stop the thread even when it has started executing.
If you have more specialised case to handle stopping case then you can do the same thing as in your example.
You can use Kotlin Coroutines also but its in Experimental phase, still you can try it out: https://kotlinlang.org/docs/reference/coroutines.html

Waiting till the async task finish its work without blocking UI thread or Main thread

I am new to multithreading in Android and I have a doubt. I have a AsyncTask instance which I call as BackGroundTask and I start this as:
BackGroundTask bgTask = new BackGroundTask();
bgTask.execute();
However I would like to wait until this call is finished its execution, before proceeding to the other statements of code without blocking UI thread and allowing user to navigate through application.
Please help me so that I can achieve this.
put your code inside onPostExecute method of AsyncTask, which you
wants to execute after work done By worker thread.
Try using bgTask.execute().get() this will wait for the background task to finish before moving to the next instruction in the called thread. (Please note that this will block the called thread until background task finishes)
I have found the answer at
How do I retrieve the data from AsyncTasks doInBackground()?
And the answer is to use callback as shown below which is copied from above shared link:
The only way to do this is using a CallBack. You can do something like this:
new CallServiceTask(this).execute(request, url);
Then in your CallServiceTask add a local class variable and class a method from that class in your onPostExecute:
private class CallServiceTask extends AsyncTask<Object, Void, Object[]>
{
RestClient caller;
CallServiceTask(RestClient caller) {
this.caller = caller;
}
protected Object[] doInBackground(Object... params)
{
HttpUriRequest req = (HttpUriRequest) params[0];
String url = (String) params[1];
return executeRequest(req, url);
}
protected onPostExecute(Object result) {
caller.onBackgroundTaskCompleted(result);
}
}
Then simply use the Object as you like in the onBackgroundTaskCompleted() method in your RestClient class.
A more elegant and extendible solution would be to use interfaces. For an example implementation see this library. I've just started it but it has an example of what you want.

How to use the Asynchronous Command in UI built using LWUIT ResourceEditor

I am using LWUIT ResrouceEditor(latest SVN code revision 1513) to generate a UI State machine.
I want to show a wait screen when a long running command is invoked by a user using a button on the current form. I believe I can use the asynchronous option when linking the command on the button. I have setup a form in which I have a button which should invoke the asynchronous command. In command selection for that button, I have set the action to show the wait screen form and have marked the command as asynchronous. However when I use the asynchronous option, the code shows the wait screen, but after that it throws a NullPointerException.
As per my understanding, once you mark a command as asynchronous, it will call the following methods from a different thread where you can handle its processing.
protected void asyncCommandProcess(Command cmd, ActionEvent sourceEvent);
protected void postAsyncCommand(Command cmd, ActionEvent sourceEvent);
However this methods are not getting called and it throws a NullPointerException.
When I looked at the LWUIT code, in UIBuilder.java(lineno. 2278), I see that it constructs the new thread for an asynchronous command as follows:
new Thread(new FormListener(currentAction, currentActionEvent, f)).start();
But when running it through Debugger I see that currentAction and currentActionEvent are always null. And hence when the FormListener thread starts running, it never calls the above two async command processing methods. Please see the listing of the run() method in the UIBuilder.java(line no. 2178)
public void run() {
if(currentAction != null) {
if(Display.getInstance().isEdt()) {
postAsyncCommand(currentAction, currentActionEvent);
} else {
asyncCommandProcess(currentAction, currentActionEvent);
// wait for the destination form to appear before moving back into the LWUIT thread
waitForForm(destForm);
}
} else {
if(Display.getInstance().isEdt()) {
if(Display.getInstance().getCurrent() != null) {
exitForm(Display.getInstance().getCurrent());
}
Form f = (Form)createContainer(fetchResourceFile(), nextForm);
beforeShow(f);
f.show();
postShow(f);
} else {
if(processBackground(destForm)) {
waitForForm(destForm);
}
}
}
}
In the above method, since the currentAction is null, it always goes into the else statement and since the nextForm is also null, it causes the NullPointerException.
On further look at the UIBuilder.java code, I noticed what is causing the NullPointer exception. It seems when the FormListner is created, it is passed currentAction and currentActionEvent, however they are null at that time. Instead the code should be changed as follows(starting at line 2264):
if(action.startsWith("#")) {
action = action.substring(1);
Form currentForm = Display.getInstance().getCurrent();
if(currentForm != null) {
exitForm(currentForm);
}
Form f = (Form)createContainer(fetchResourceFile(), action);
beforeShow(f);
/* Replace following with next lines for fixing asynchronous command
if(Display.getInstance().getCurrent().getBackCommand() == cmd) {
f.showBack();
} else {
f.show();
}
postShow(f);
new Thread(new FormListener(currentAction, currentActionEvent, f)).start();
*/
new Thread(new FormListener(cmd, evt, f)).start();
return;
}
Can lwuit development team take a look at the above code, review and fix it. After I made the above change, the asynchronous command processing methods were invoked.
Thank you.
Thanks for the information, its probably better to use the issue tracker for things like this (at http://lwuit.java.net).
I will make a similar change although I don't understand why you commented out the form navigation portion.
To solve your use case of a wait screen we have a much simpler solution: Next Form. Just show the wait screen and in it define the "Next Form" property.
This will trigger a background thread to be invoked (processBackground callback) and only when the background thread completes the next form will be shown.

JavaFX Multi Threading

I'm writing a small programm where JavaFx acts as a viewer and controler and let Java do the other hard work. I can start multiple threads from Javafx however, I'm not able to stop them. If I try to use .stop(), the threads are still running.
Here is one of them:
public var sleepTask_connect;
function LogOutAction(): Void {
sleepTask_connect.stop();
}
function LogInAction(): Void {
var listener = FXListener_interface_connection {
override function callback(errorCode, errorMessage): Void {
//do something
if(errorCode != 200){
setIcn(errorMessage);
}
}
}
sleepTask_connect = FXListener_connection {
listener: listener
};
sleepTask_connect.start();
}
Use JavaTaskBase to implement you Java thread. There is a stop method to kill the thread. Here is an example of how you use it.
I've had better luck with the JFXtras XWorker component for threading. See http://jfxtras.googlecode.com/svn/site/javadoc/release-0.6/org.jfxtras.async/org.jfxtras.async.XWorker.html.
However in general in order for your thread to respond to cancel/stop requests, you have to check the canceled or stopped flag in your code during your "do something" section. This works if your thread is in an infinite loop for example, or if you just have a series of long running processes you can check for canceled/stopped in between them. Alternatively, if your code calls some blocking method (like sockets or a blocking queue), then most of these will throw an InterruptedException when the thread is canceled.

Resources