Until now I used to await my Tasks before continuing processing.
But now I plant to do something meaningful instead of awaiting
A normal async method where you await before continuing would be like:
async Task Fasync()
{
A();
await OtherAsync();
B();
}
I am certain that B will not be called, before both A and OtherAsync have executed all their statements. I can be certain that before processing B OtherAsync has reached its postcondition.
I've noticed that the thread that continues after the await usually has a different thread Id. I assume this means that a different thread can continue the processing of my code after my await.
Now let's create a function that does not await:
async Task Gasync()
{
K();
Task taskF = Fasync(); // call Fasync defined above. Do not await yet
L();
await taskF; // await until Fasync completed
M();
}
Writing diagnostic messages showed me that the procedures are called in the following order:
K()
within Fasync(): A(), OtherAsync()
L()
So Gasync continues processing only after Fasync starts awaiting. L is not started before A returned.
Officially - as a user of Fasync - I may only rely on the pre-condition and the postcondition of Fasync. I may not assume anything about how Fasync gets to its post condition; I may not assume anything about the order in which Fasync does its work.
This gives the designer of Fasync the freedom to change his procedure without having to worry about assumptions that the caller made, as long as he meets the proper postcondition.
Just out of curiosity:
What happens if thread X is processing L and OtherAsync completes?
Does thread X continue processing L, while at the same time a different thread Y continues Fasync by processing M?
Is processing Gasync suspended until Fasync completes?
Is processing Fasync suspended until Gasync awaits for Fasync?
There's a few points that are worth understanding about async, all covered in my async intro:
Every async method begins executing synchronously; it can only become asynchronous when it encounters an await.
await may also act synchronously if its awaitable is already complete.
When await acts asynchronously, by default it captures the current context and uses that context to resume executing the async method when its awaitable completes.
Those three points can answer your questions.
Specifically:
What happens if thread X is processing L and OtherAsync completes?
As soon as OtherAsync completes, the continuation of Fasync is able to run. Whether it actually runs right away or not depends on the context captured by the await in Fasync. If it captured the thread pool context (or if ConfigureAwait(false) was used), then the continuation of Fasync is queued to the thread pool, where it can be run immediately by any thread pool thread, and that thread may execute B in parallel with L. However, if that await captured a UI thread context, then the continuation of Fasync is queued to the UI message processing loop, and (assuming X is the UI thread in this case), it will wait until X is free to continue executing Fasync.
Does thread X continue processing L, while at the same time a different thread Y continues Fasync by processing M?
If the Fasync await captured the thread pool context, then this is possible.
Is processing Gasync suspended until Fasync completes?
No. When there is a continuation ready to execute, it is queued. It never interrupts an executing thread. L has started, and L will run to completion before that thread is used for anything else. Once L has completed and Gasync does its await, then the Gasync method can be suspended.
Is processing Fasync suspended until Gasync awaits for Fasync?
Possibly. If the Fasync await captured a UI context (and X is the UI thread), then the Fasync continuation is queued. Assuming there are awaits "all the way up", then the await in Gasync will yield to the UI message loop, which will pull Fasync's continuation from its message queue and execute it.
In conclusion, you mention "preconditions" and "postconditions" a few times in your question. As you work more with async and await, you'll find that async will gently push you in a more functional direction. It's just easier to pass data into the methods and extract results from the returned values rather than worrying about state and preconditions and postconditions. So the concepts of "precondition" and "postcondition" tend to fade in the async world; as the code becomes more asynchronous, side effects become minimized.
Related
quarkus reactive uses mutiny to handle task asynchronously.
But, the flow is always wait every job to finish, then returns the result.
Sometime, I just want to trigger a job and let it run in the background without waiting it to be done.
Any suggestion or example?
Uni<Integer> mainJob() {
// fake logic
return Uni.createFrom().item(1);
}
Uni<Void> sideJob(int n) {
// fake logic
logger.log("result = " + n);
}
#Path("test")
Uni<Integer> testExample() {
return mainJob().onItem().call(n -> sideJob(n));
}
The upper code only returns after sideJob() is done. But, I just want to return the result immediately once mainJob is done, with sideJob triggered and run in background.
Any suggestion on it?
ManagedExecutor may be a way to do but it seems not natural in this case. The side job may/not be long running.
According to the Uni interface documentation:
To trigger the computation, a UniSubscriber must subscribe to the Uni. It will be notified of the outcome once there is an item or failure event fired by the observed Uni. A subscriber receives (asynchronously) a UniSubscription and can cancel the demand at any time.
Thus, the only way to start the execution of a Uni is by subscribing to it, even by calling uni.await().indefinitely() you are, in fact, subscribing to the Uni as we can see in the documentation of the indefinitely() method:
Subscribes to the Uni and waits (blocking the caller thread) indefinitely until a item event is fired or a failure event is fired by the upstream uni.
Invoking the call() method is nothing more than chaining a new function that will be included in the stream that will be executed when the Uni is subscribed. This way, when the testExample() method returns the result of the call(), it is not executing and waiting for the Uni to finish, it is actually returning the result immediately.
However, whoever is going to receive the final result must wait for the Uni stream to finish, so the client waiting for the HTTP response will be waiting for the sideJob() to finish in order to receive the original value, but once again, your testExample() method is not waiting for anything, it returns the Uni immediately without waiting for it to be executed.
I was just going back to Servlet-3.x features and exploring it. If I am not wrong, before Servlet-3.x it was thread per request model and it would run out of threads in the pool, for heavy incoming traffic.
So, with Servlet-3.x it says it is Asynchronous and doesn't keep the threads blocked , rather releases them immediately but just the task is delegated.
Here is my interpretation,
consider there are 2 threads in Server thread-pool
For a new Async Servlet request R1 there is a thread T1, this T1 would delegate the task to T2 and T1 responds back to client immediately.
Question: Is T2 created from Server thread-pool? If so, I don't get the point.
Case 1: If it was old Synchronous Servlet request T1 would have been busy running I/O task,
Case 2: If it was Asynchronous Servlet call T2 is busy running I/O task.
In both cases, one of them is busy.
I tried to check the same with a sample Async servlet in openliberty app server, below is the sample log captured from my sample demo Servlet.
Entering doGet() == thread name is = Default Executor-thread-116
Exiting doGet() == thread name is = Default Executor-thread-116
=== Long running task started ===
Thread executing #start of long running task = Default Executor-thread-54
Thread executing #end of long running task = Default Executor-thread-54
=== Long running task ended ===
As shown above, the Default Executor-thread-116 is released immediately and delegated long running task to the Default Executor-thread-54, but I am not sure if they are from the App Server thread pool. If so, why can't just Default Executor-thread-116 do the task instead of delegation?
Can someone throw some light on this async behavior of Servlets in JavaEE
In your example, where the work is synchronous and there's no separate executor/threadpool, there is nearly no point to use async servlets. Lots of samples/examples out there are just block on a 2nd thread because they're trying to illustrate just the syntax.
But there's no reason why you can't spin off a thread to do a little work, add your async context to some list, and then after some event (inbound JMS, websocket, whatever) provides the data needed to complete the async response. For example, a 2-player game server wouldn't wait for player 2 in a second thread, it would just have their async context floating around in memory waiting for a 2nd player to find it.
My OnAppearing code looks like this. I don't understand what this is added for:
`await Task.Yield()`
Can someone explain what this does?
protected override async void OnAppearing()
{
base.OnAppearing();
Utils.SetState(Settings.mode.Text(), vm.Mode);
vm.CfsLabel = Settings.cfs.Text();
SetMode(Settings.mode.Text());
Subscribe();
ContentPageStack.IsVisible = true;
if (!openedOnce)
{
// can someone explain what the following line
// is doing here in the code. What's the Task
// that it refers to and what does Yield do?
await Task.Yield();
await scroll.ScrollToAsync(0, 0, false);
openedOnce = true;
}
if (App.devIsUser)
Analytics.TrackEvent(VersionTracking.CurrentVersion + " - On Appearing - home page");
}
In this particular case, await Task.Yield does nothing useful. It is probably a misguided attempt to process Win32 messages like WM_PAINT. I.e., a "poor man's DoEvents".
await Task.Yield is used to force asynchrony. It's a way of forcing await to behave asynchronously, returning to the caller. It also immediately queues the remainder of the method to run.
The reason this doesn't work as a "poor man's DoEvents" is because the Win32 message queue is prioritized. So this is what the await Task.Yield actually does in this particular instance:
Queues the continuation of the async method to the current context (the UI SynchronizationContext), which places the continuation into the Win32 message queue.
Returns from the async method. Since this is an event handler, this returns to the Win32 message processing loop.
The Win32 message process loop pulls the next message from its queue. Since the queue is prioritized, it will always skip over regular Win32 messages and take the continuation message.
The loop processes the message, which runs the continuation of the async method, so the event handler resumes executing right where it left off.
I think the Microsoft docs give you a clear picture of what it does, When you read about Task.Yield its says:
Creates an awaitable task that asynchronously yields back to the current context when awaited.
Returns
YieldAwaitable
A context that, when awaited, will asynchronously transition back into the current context at the time of the await. If the current SynchronizationContext is non-null, it is treated as the current context. Otherwise, the task scheduler that is associated with the currently executing task is treated as the current context.
What this basically means is when you use await Task.Yield in an async method it will force the method to complete asynchronously. And if there is a Synchronization Context available it will execute the remainder of the method's execution back to that context.
Note: The synchronization context that is present on a UI thread in most UI environments will often prioritize work posted to the context higher than input and rendering work. For this reason, do not rely on await Task.Yield(); to keep a UI responsive.
i am building an application for clients to get questions from server and answer it, if the server doesn't have questions i want to go to new screen and print message that try again in few minutes, getting questions is in AsyncTask , if the server doesn't have questions , it will sends in the header of the responds, a header isFindAQuestion with the value false, here is the code on client to ensure if false , i print on LogCat and i see the message = false, but my problems that even if i start new activity with the intent, this activity keep working and show me exception and it is null pointer exception because on the onPostExceute will take a parmeter null and try to process it, i put finish() in the end of false statement but doesn't finish the activity
if (response.getFirstHeader("isFindAQuestion").getValue()
.toString().equals("false")) {
Log.d("message", "false");
Bundle basket = new Bundle();
basket.putString("Message", "sorry no enought questions");
Intent goToAnswerQuestion = new Intent(AnswerQuestion.this,
FinishTime.class);
goToAnswerQuestion.putExtras(basket);
startActivity(goToAnswerQuestion);
finish();
}
Editis it because AsyncTask is working on thread so if the activity is finished, that thread will keep working? and if so how can i stop that thread?
doInBackground is not executed in the UI thread, but in a separeted thread:
invoked on the background thread immediately after onPreExecute()
finishes executing. This step is used to perform background
computation that can take a long time.
If you want to stop your background operation and perform some activities on the UI thread the better thing is to call cancel() and then perform all the stuff you want in the onCancelled callback wich is executed on the UI thread.
From the AsyncTask documentation:
A task can be cancelled at any time by invoking cancel(boolean).
Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns.
To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
protected void onCancelled (Result result)
Runs on the UI thread after cancel(boolean) is invoked and doInBackground(Object[]) has finished.
The default implementation simply invokes onCancelled() and ignores the result. If you write your own implementation, do not call super.onCancelled(result).
According to MSDN:
The WaitForSingleObject function can wait for the following objects:
Change notification
Console input
Event
Memory resource notification
Mutex
Process
Semaphore
Thread
Waitable timer
Then we can use WaitForSingleObject to make the parent-thread wait for child ones.
int main()
{
HANDLE h_child_thread = CreateThread(0,0, child, 0,0,0); //create a thread in VC
WaitForSingleObject(h_child_thread, INFINITE); //So, parent-thread will wait
return 0;
}
Question
Is there any other way to make parent-thread wait for child ones in VC or Windows?
I don't quite understand the usage of WaitForSingleObject here, does it mean that the thread's handle will be available when the thread terminates?
You can establish communication between threads in multiple ways and the terminating thread may somehow signal its waiting thread. It could be as simple as writing some special value to a shared memory location that the waiting thread can check. But this won't guarantee that the terminating thread has terminated when the waiting thread sees the special value (ordering/race conditions) or that the terminating thread terminates shortly after that (it can just hang or block on something) and it won't guarantee that the special value gets ever set before the terminating thread actually terminates (the thread can crash). WaitForSingleObject (and its companion WaitForMultipleObjects) is a sure way to know of a thread termination when it occurs. Just use it.
The handle will still be available in the sense that its value won't be gone. But it is practically useless after the thread has terminated, except you need this handle to get the thread exit code. And you still need to close the handle in the end. That is unless you're OK with handle/memory leaks.
for the first queation - yes. The method commonly used here is "Join". the usage is language dependant.
In .NET C++ you can use the Thread's Join method. this is from the msdn:
Thread* newThread = new Thread(new ThreadStart(0, Test::Work));
newThread->Start();
if(newThread->Join(waitTime + waitTime))
{
Console::WriteLine(S"New thread terminated.");
}
else
{
Console::WriteLine(S"Join timed out.");
}
Secondly, the thread is terminated when when you are signaled with "WaitForSingleObject" but the handle is still valid (for a terminated thread). So you still need to explicitly close the handle with CloseHandle.