How to Ensure to Run Some Code on Same Background Thread

Running code in the background and validating the thread

My guess is you have to specify the type of thread priority with setThreadPriority. Try as follows:

new Thread(new Runnable() {
public void run() {
// moves the current Thread into the background
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_BACKGROUND);

// doing some work in the background here
Log.d(tag, "Thread: " + checkThread());
}
}).start();

This should be return background.

How can I run code in a background thread and still access the UI?

While I'm glad you found a solution, I advise against using Application.DoEvents() because it is bad practice.

Please see this blog post: Keeping your UI Responsive and the Dangers of Application.DoEvents.

Simply put, Application.DoEvents() is a dirty workaround that makes your UI seem responsive because it forces the UI thread to handle all currently available window messages. WM_PAINT is one of those messages which is why your window redraws.

However this has some backsides to it... For instance:

  • If you were to close the form during this "background" process it would most likely throw an error.

  • Another backside is that if the ScanButtonInForm1() method is called by the click of a button you'd be able to click that button again (unless you set Enabled = False) and starting the process once more, which brings us to yet another backside:

  • The more Application.DoEvents()-loops you start the more you occupy the UI thread, which will cause your CPU usage to rise rather quickly. Since every loop is run in the same thread your processor cannot schedule the work over different cores nor threads, so your code will always run on one core, eating as much CPU as possible.

The replacement is, of course, proper multithreading (or the Task Parallel Library, whichever you prefer). Regular multithreading actually isn't that hard to implement.


The basics

In order to create a new thread you only need to declare an instance of the Thread class and pass a delegate to the method you want the thread to run:

Dim myThread As New Thread(AddressOf <your method here>)

...then you should set its IsBackground property to True if you want it to close automatically when the program closes (otherwise it keeps the program open until the thread finishes).

Then you just call Start() and you have a running background thread!

Dim myThread As New Thread(AddressOf myThreadMethod)
myThread.IsBackground = True
myThread.Start()


Accessing the UI thread

The tricky part about multithreading is to marshal calls to the UI thread. A background thread generally cannot access elements (controls) on the UI thread because that might cause concurrency issues (two threads accessing the same control at the same time). Therefore you must marshal your calls to the UI by scheduling them for execution on the UI thread itself. That way you will no longer have the risk of concurrency because all UI related code is run on the UI thread.

To marhsal calls to the UI thread you use either of the Control.Invoke() or Control.BeginInvoke() methods. BeginInvoke() is the asynchronous version, which means it doesn't wait for the UI call to complete before it lets the background thread continue with its work.

One should also make sure to check the Control.InvokeRequired property, which tells you if you already are on the UI thread (in which case invoking is extremely unnecessary) or not.

The basic InvokeRequired/Invoke pattern looks like this (mostly for reference, keep reading below for shorter ways):

'This delegate will be used to tell Control.Invoke() which method we want to invoke on the UI thread.
Private Delegate Sub UpdateTextBoxDelegate(ByVal TargetTextBox As TextBox, ByVal Text As String)

Private Sub myThreadMethod() 'The method that our thread runs.
'Do some background stuff...

If Me.InvokeRequired = True Then '"Me" being the current form.
Me.Invoke(New UpdateTextBoxDelegate(AddressOf UpdateTextBox), TextBox1, "Status update!") 'We are in a background thread, therefore we must invoke.
Else
UpdateTextBox(TextBox1, "Status update!") 'We are on the UI thread, no invoking required.
End If

'Do some more background stuff...
End Sub

'This is the method that Control.Invoke() will execute.
Private Sub UpdateTextBox(ByVal TargetTextBox As TextBox, ByVal Text As String)
TargetTextBox.Text = Text
End Sub

New UpdateTextBoxDelegate(AddressOf UpdateTextBox) creates a new instance of the UpdateTextBoxDelegate that points to our UpdateTextBox method (the method to invoke on the UI).

However as of Visual Basic 2010 (10.0) and above you can use Lambda expressions which makes invoking much easier:

Private Sub myThreadMethod()
'Do some background stuff...

If Me.InvokeRequired = True Then '"Me" being the current form.
Me.Invoke(Sub() TextBox1.Text = "Status update!") 'We are in a background thread, therefore we must invoke.
Else
TextBox1.Text = "Status update!" 'We are on the UI thread, no invoking required.
End If

'Do some more background stuff...
End Sub

Now all you have to do is type Sub() and then continue typing code like if you were in a regular method:

If Me.InvokeRequired = True Then
Me.Invoke(Sub()
TextBox1.Text = "Status update!"
Me.Text = "Hello world!"
Label1.Location = New Point(128, 32)
ProgressBar1.Value += 1
End Sub)
Else
TextBox1.Text = "Status update!"
Me.Text = "Hello world!"
Label1.Location = New Point(128, 32)
ProgressBar1.Value += 1
End If

And that's how you marshal calls to the UI thread!


Making it simpler

To make it even more simple to invoke to the UI you can create an Extension method that does the invoking and InvokeRequired check for you.

Place this in a separate code file:

Imports System.Runtime.CompilerServices

Public Module Extensions
''' <summary>
''' Invokes the specified method on the calling control's thread (if necessary, otherwise on the current thread).
''' </summary>
''' <param name="Control">The control which's thread to invoke the method at.</param>
''' <param name="Method">The method to invoke.</param>
''' <param name="Parameters">The parameters to pass to the method (optional).</param>
''' <remarks></remarks>
<Extension()> _
Public Function InvokeIfRequired(ByVal Control As Control, ByVal Method As [Delegate], ByVal ParamArray Parameters As Object()) As Object
If Parameters IsNot Nothing AndAlso _
Parameters.Length = 0 Then Parameters = Nothing

If Control.InvokeRequired = True Then
Return Control.Invoke(Method, Parameters)
Else
Return Method.DynamicInvoke(Parameters)
End If
End Function
End Module

Now you only need to call this single method when you want to access the UI, no additional If-Then-Else required:

Private Sub myThreadMethod()
'Do some background stuff...

Me.InvokeIfRequired(Sub()
TextBox1.Text = "Status update!"
Me.Text = "Hello world!"
Label1.Location = New Point(128, 32)
End Sub)

'Do some more background stuff...
End Sub


Returning objects/data from the UI with InvokeIfRequired()

With my InvokeIfRequired() extension method you can also return objects or data from the UI thread in a simple manner. For instance if you want the width of a label:

Dim LabelWidth As Integer = Me.InvokeIfRequired(Function() Label1.Width)


Example

The following code will increment a counter that tells you for how long the thread has run:

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim CounterThread As New Thread(AddressOf CounterThreadMethod)
CounterThread.IsBackground = True
CounterThread.Start()

Button1.Enabled = False 'Make the button unclickable (so that we cannot start yet another thread).
End Sub

Private Sub CounterThreadMethod()
Dim Time As Integer = 0

While True
Thread.Sleep(1000) 'Wait for approximately 1000 ms (1 second).
Time += 1

Me.InvokeIfRequired(Sub() Label1.Text = "Thread has been running for: " & Time & " seconds.")
End While
End Sub


Hope this helps!

How to run task using Thread in Background

please check the sample -

 public class EventHandlerImplementation extends EventHandler {
private EventHandlerImplementation(EventRunner runner) {
super(runner);
}

@Override
public void processEvent(InnerEvent event) {
getUITaskDispatcher().asyncDispatch(() -> {
// do your stuff here
});
}
}

Correct way to communicate the result of a background thread to the Ui Thread in Android

Background

In Android, when an application is launched, the system creates a thread of execution for the application, called main thread (also known as the UI thread). Google introduces the main thread and its responsible as below.

The main thread has a very simple design: Its only job is to take and
execute blocks of work from a thread-safe work queue until its app is
terminated. The framework generates some of these blocks of work from
a variety of places. These places include callbacks associated with
lifecycle information, user events such as input, or events coming
from other apps and processes. In addition, app can explicitly enqueue
blocks on their own, without using the framework.

Nearly any block of code your app executes is tied to an event
callback, such as input, layout inflation, or draw. When something
triggers an event, the thread where the event happened pushes the
event out of itself, and into the main thread’s message queue. The
main thread can then service the event.

While an animation or screen update is occurring, the system tries to
execute a block of work (which is responsible for drawing the screen)
every 16ms or so, in order to render smoothly at 60 frames per second.
For the system to reach this goal, the UI/View hierarchy must update
on the main thread. However, when the main thread’s messaging queue
contains tasks that are either too numerous or too long for the main
thread to complete the update fast enough, the app should move this
work to a worker thread. If the main thread cannot finish executing
blocks of work within 16ms, the user may observe hitching, lagging, or
a lack of UI responsiveness to input. If the main thread blocks for
approximately five seconds, the system displays the Application Not
Responding (ANR) dialog, allowing the user to close the app directly.

To update a View, you must do it on the main thread, if you try to update in a background thread, the system will throw CalledFromWrongThreadException.

How to update a View on the main thread from a background thread?

The main thread has a Looper and a MessageQueue assigned with it. To update a View, we need to create a task then put it to the MessageQueue. To do that Android provides
Handler API which allows us to send a task to the main thread's MessageQueue for executing later.

// Create a handler that associated with Looper of the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());

// Send a task to the MessageQueue of the main thread
mainHandler.post(new Runnable() {
@Override
public void run() {
// Code will be executed on the main thread
}
});

To help developers easy to communicate with the main thread from a background thread, Android offers several methods:

  • Activity.runOnUiThread(Runnable)

  • View.post(Runnable)

  • View.postDelayed(Runnable, long)

Under the hood, they use Handler API to do their jobs.

Back to your question

AsyncTask

This is a class that is designed to be a helper class around Thread and Handler. It's responsible for:

  • Create a thread or pool of thread to do a task in the background

  • Create a Handler that associated with the main thread to send a task to the main thread's MessageQueue.

  • It is deprecated from API level 30

ThreadPoolExecutor

Create and handle a thread in Java is sometimes hard and might lead to a lot of bugs if developers do not handle it correctly. Java offers the ThreadPoolExecutor to create and manage threads more efficiently.

This API does not provide any method to update the UI.

Kotlin Coroutines

Coroutines is a solution for asynchronous programming on Android to simplify code that executes asynchronously. But it only available for Kotlin.

So my question is, what is the correct way of communicate the result
of background thread when this finish?.

1. Using Handler or mechanism built on Handler

1.1. If a thread is bounded with Activity/Fragment:

  • Activity.runOnUiThread(Runnable)

1.2. If a thread has a reference to a view, such as Adapter class.

  • View.post(Runnable)

  • View.postDelayed(Runnable, long)

1.3. If a thread does not bound to any UI element, then create a Handler on your own.

Handler mainHandler = new Handler(Looper.getMainLooper);

Note: A benefit of using Handler is you can use it to do 2 ways communication between threads. It means from a background thread you can send a task to the main thread's MessageQueue and from the main thread, you can send a task to the background's MessageQueue.

2. Using BroadcastReceiver

This API is designed to allow Android apps can send and receive broadcast messages from the Android system, other apps or components (Activity, Service, etc) inside the app, similar to publish-subscribe design partern.

Because of the BroadcastReceiver.onReceive(Context, Intent) method is called within the main thread by default. So you can use it to update the UI on the main thread. For example.

Send data from a background thread.

// Send result from a background thread to the main thread
Intent intent = new Intent("ACTION_UPDATE_TEXT_VIEW");
intent.putExtra("text", "This is a test from a background thread");
getApplicationContext().sendBroadcast(intent);

Receive data from activity/fragment

// Create a broadcast to receive message from the background thread
private BroadcastReceiver updateTextViewReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String text = intent.getStringExtra("text");
myTextView.setText(text);
}
};

@Override
protected void onStart() {
super.onStart();
// Start receiving the message
registerReceiver(updateTextViewReceiver, new IntentFilter("ACTION_UPDATE_TEXT_VIEW"));
}

@Override
protected void onStop() {
// Stop receving the message
unregisterReceiver(updateTextViewReceiver);
super.onStop();
}

This method is usually used to communicate between Android apps or Android apps with the system. Actually, you can use it to communicate between components in Android app, such as (Activity, Fragment, Service, Thread, etc.), but it requires a lot of code.

If you want a similar solution but less code, easy to use, then you can use the following method.

3. Using EventBus

EventBus is a publish/subscribe event bus for Android and Java. If you want to execute a method that runs on the main thread, just mark it with @Subscribe(threadMode = ThreadMode.MAIN) annotation.

// Step 1. Define events
public class UpdateViewEvent {
private String text;

public UpdateViewEvent(String text) {
this.text = text;
}

public String getText() {
return text;
}
}

// Step 2. Prepare subscriber, usually inside activity/fragment
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
myTextView.setText = event.getText();
};

// Step 3. Register subscriber
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

// Step 4. Unregister subscriber
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}

// Step 5. Post events from a background thread
UpdateViewEvent event = new UpdateViewEvent("new name");
EventBus.getDefault().post(event);

This is useful when you want to update a View when the activity/fragment is visible to users (they are interacting with your app).

Run Service in background Thread

Okay... Here is completed code: https://mega.nz/#!yUsjgJyZ!DHfuBqsujAHurS-pQ_W5y8BAflOtvxsm48goRPkDsxA

First, i want to tell you what is my goal:

When I run program, i want the progress bar to be in indeterminate state. After pressing the button, i want progress bar to reflect progress of Service. After finishing the Service, i want the progress bar to be completed (100%).

Here is what i have found. It looks like service automatically runs it's task on background thread. I have built a "sand box" program where i was playing with services and progress bar. The program comprised of progress bar, two text fields with two buttons above them. First button can start service_countTo100 and second button can run service_getActualCount.

Now in fxml file i set progress bar to indeterminate default state. After pressing the button1, a counting has started (displayed in text_field1) and progress bar has changed according to actual progress. After pressing button2, actual value of count is displayed in text_field2. And here comes some issues. To demonstrate the issues, i will show you source code of Service:

// Create the service
public static Service<Integer> serviceTo100 = new Service<Integer>() {
@Override
protected Task<Integer> createTask() {
Task<Integer> taskTo100 = new Task<Integer>() {
@Override protected Integer call() throws Exception {

int iterations;
updateProgress(-1, 100);
for (iterations = 0; iterations < 100; iterations++) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}

updateMessage("Iteration " + iterations);
updateProgress(iterations, 100);

// Now block the thread for a short time, but be sure
// to check the interrupted exception for cancellation!
try {
Thread.sleep(100);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
}
}

//udpateProgress(100, 100);
return iterations;
}
};
return taskTo100;
}
};

As you can see, there is a simple loop which counts from 0 to 100 and there is also a updateProgress(iterations, 100); statement which updates progress. This service is located in Services class. In FXMLDocumentController.java is method called runService(Service service) defined as this:

public void runService(Service service){

service.start();
progressBar.progressProperty().bind(service.progressProperty());

service.setOnSucceeded((event) -> {
service.reset();
progressBar.progressProperty().unbind();
progressBar.setProgress(1);
});
}

The initialize looks like this:

@Override
public void initialize(URL url, ResourceBundle rb) {
btn_start1.setOnAction((event) -> {

Service service = Services.serviceTo100;
runService(service);
txt_field1.textProperty().bind(service.messageProperty());
System.out.printf("something\n");

});
.
.
.
}//end of initialize

Now the most interesting thing (at least for me, novice) comes into play.

In service definition, you can notice commented line //updateProgress(100,100). That was my try to set progress bar to completed state when counting has stopped. But java ignored that line. I tried to put System.out.print("Something"); and it worked, but updateProgress(100, 100) didn't. When counting has finished, progress bar was set to it's default state defined in fxml file, which was indeterminate.

Conclusion: Service class creates task defined inside of it and after task is completed, the task doesn't exists anymore, thus, there is no progress to be bound with progress bar.

Even though task does not exists anymore, you cannot set progress of the bounded progress bar with setProgress(double double) method. You first need to unbound it.

Now I got what i needed:

You run the program, progress bar is in indeterminate state, waiting for hit. You hit the button, service starts counting up to 100 and progress bar is progressing according to progressProperty of service. When counting is done, Progress bar is set to indeterminate state again, waiting for another start.



Related Topics



Leave a reply



Submit