Does "await Task.CompletedTask" do anything? - async-await

I'm curious about this statement:
await Task.CompletedTask;
I know that it nominally doesn't do anything practical, but what I'm wondering is whether it actually causes the running function to exit, then resume at the statement after the await, or whether it truly does nothing and doesn't interrupt the thread at all.
This might make a difference in the sense that it would cause the current run loop to complete and resume, and if the run loop is the main thread it would mean that UI changes got committed.
The documentation doesn't explain it, and I can't figure out a good way to decide which it is.
Thanks,
Frank

whether it actually causes the running function to exit, then resume at the statement after the await, or whether it truly does nothing and doesn't interrupt the thread at all.
await will first test its awaitable to see if it is already complete, and if it is, it will continue executing synchronously.
If you want to force an asynchronous function to yield, then use await Task.Yield();. Side note: this should be extremely rare in production code, but it's sometimes useful for unit tests.

Related

How to debug an asynchronous RFC - Starting new task...Performing...on end of task?

I am a beginner in SAP ABAP. I am debugging an asynchronous RFC (parallel processing). I have put a break-point in the calling portion of the RFC, an external break-point inside the RFC and an external break point in the form which is called at the end of task through perform. I am able to debug the RFC FM.
Another session opens up. But I am not able to debug the perform which is called after end of task. After the RFC is debugged, the control returns to the calling point of the FM. it doesn't go inside the form. When all the iterations are finished, then at the end it goes inside the perform. Why so? shouldn't the perform be executed in parallel?
Inside the perform I have written like RECEIVE RESULTS FROM FUNCTION XXX. But the debugger control is not going inside the perform after returning from the RFC.
You have given very little information on the overall program flow, but there's a part of the documentation that might be relevant to your case:
A prerequisite for the execution of a registered callback routine is
that the calling program still exists in its internal session when
the remote function is terminated. It is then executed here at the
next change of the work process in a roll-in. If the program was
terminated or is located on the stack as part of a call sequence, the
callback routine is not executed.
[...]
The time when the callback routines are executed can be programmed
explicitly or be reached implicitly:
The statement WAIT FOR ASYNCHRONOUS TASKS is used for explicit programming. As specified by a condition, this statement changes the
work process and hence executes the callback routines registered up to
this time. It waits for as many registered routines to end until the
condition is met (the maximum wait time can be restricted). Explicit
programming is recommended whenever the results of the remote function
are required in the current program.
If the results of the remote function are not required in the current program, the time at which the callback routines are executed
can also be determined by an implicit change of the work process (for
example, at the end of a dialog step). This can be a good idea, for
example, in GUI scenarios in which uses of WAIT are not wanted. In
this case, it must be ensured that the work process changes before the
program is ended. There is also a risk that, if the work process is
changed implicitly, not all callback routines are registered in time.
It is likely that the program issuing the call and registering the callback routine is either terminated or does not issue a WAIT FOR ASYNCHRONOUS TASKS so that the callback is only executed on the next roll-in.
Re-reading your question, you apparently assume that the callback routine will be executed in parallel to the program that has registered it. That is not the case, ABAP is not multi-threaded.

waitpid in infitine wait state after PTRACE_ATTACH

I have integrated Google-Breakpad in my C++ application. Now, I am deliberately crashing the application but it hangs-up in my Ubuntu i686 system. I have to put printf everywhere in Breakpad to check where exactly it is hanging. So, in breakpad, a clone child process is being created and in that process ptrace(PTRACE_ATTACH, pid, NULL, NULL) followed by waitpid(pid, NULL, __WALL) syscall is being called on every thread. With one particular thread waitpid is entering in infinite wait state and I then have to deliberately kill the application.
Does anyone knows why exactly this is happening? Why with this one particular thread waitpid() is going in infinte wait state? Is there any solution for the same?
Thanks.
In general, PTRACE_ATTACH does not guarantee that a process will have anything to report. After PTRACE_ATTACH, waitpid will trigger only if one of two things happen:
The debugee receives a signal.
The debugee exists.
Some things are tantamount to one of those things. For example, if the debugee calls execve, then after a successful execution the kernel makes it appear as if the debugee received a TRAP signal.
If none of those situations happen, there is no reason for PTRACE_ATTACH to do anything at all.
If you want waitpid to return (say, because you want to change the debugee's state), then simply send a signal to the thread after calling PTRACE_ATTACH. This will guarantee that the thread have something to tell you.

Best practice for making some failed requests stop a thread, allowing others to continue

I have what I assume is a common scenario, and while I believe I have a working solution, it feels like there's probably a better way.
The issue is that I need finer granularity than the Thread Group-level Action to be taken after a Sampler error behavior. Some of my samplers represent requests that would prevent further execution of a workflow on failure. In these cases, rather than barreling ahead with subsequent requests that a real user could not make and that would fail anyway, I want the thread to move on to the next iteration loop, starting from scratch, as it were. Other samplers represent requests that would continue to be made even if some of them failed. In these cases, I want the thread to keep going.
The method I'm using now, which is clunky but seems to work, is as follows: at the Thread-Group level I have set the Action to be taken after a Sampler error to be Continue. I assume this means that by default, if a Sampler fails, the thread will continue with the next instructions until it reaches the end.
This leaves requests that I want to block/halt/restart the workflow on a failure. The solution I have found is to follow each of these Critical Actions with an If Controller:
The condition !${JMeterThread.last_sample_ok} should resolve to true if the previous Sample failed. Within the If Controller, I have a Test Action to stop execution and start the next loop iteration of the thread:
I assume Go to next loop iteration means to start the thread over, assuming the Thread Group is set up with a loop count.
This set up seems to work, in that the thread starts over at the top of the tree each time a Sampler fails and is followed by this If/Action combo. Samplers that are not followed by this block do not halt execution on a failure.
This set up also seems very clunky, and annoying, since I'm copy-pasting this failure conditional all over the place. Is there a more elegant way of getting this behavior, or have I hit upon the more-or-less right way of doing this? Thanks!
Your solution is fine except for copy/paste as you say, so the solution is to use:
Test Fragment will contain your IfController:
Module Controller will point to it:

Is it possible to advance a deadlocked thread? stuck at WaitForSingleObject

If I have an app that is creating threads which do their work and then exit, and one or more threads get themselves into a deadlock (possibly through no fault of my own!), is there a way of programmatically forcing one of the threads to advance past the WaitForSingleObject it might be stuck at, and thus resolving the deadlock?
I don't necessarily want to terminate the thread, I just want to have it move on (and thus allow the threads to exit "gracefully".
(yes, I know this sounds like a duplicate of my earlier question Delphi 2006 - What's the best way to gracefully kill a thread and still have the OnTerminate handler fire?, but the situation is slightly different - what I'm asking here is whether it is possible to make a WaitForSingleObject (Handle, INFINTE) behave like a WaitForSingleObject (Handle, ItCantPossiblyBeWorkingProperlyAfterThisLong)).
Please be gentle with me.
* MORE INFO *
The problem is not necessarily in code I have the source to. The actual situation is a serial COM port library (AsyncFree) that is thread based. When the port is USB-based, the library seems to have a deadlock between two of the threads it creates on closing the port. I've already discussed this at length in this forum. I did recode one of the WaitForSingleObject calls to not be infinite, and that cured that deadlock, but then another one appeared later in the thread shutdown sequence, this time in the Delphi TThread.Destroy routine.
So my rationale for this is simple: when my threads deadlock, I fix the code if I can. If I can't, or one appears that I don't know about, I just want the thread to finish. I doesn't have to be pretty. I can't afford to have my app choke.
You can make a handle used in WaitForSingleObject invalid by closing it (from some other thread). In this case WaitForSingleObject should return WAIT_FAILED and your thread will be 'moved on'
If you don't use INFINITE but just set a given timeout time, you can check if the call returned because the time out time expired or because the handle you were waiting for got into the signalled state. Then your code can decide what to do next. Enter another waiting cycle, or simply exit anyway maybe showing somewhere 'hey, I was waiting but it was too long and I terminated anyway).
Another options is to use WaitForMultipleObjects and use something alike an event to have the wait terminate if needed. The advantage it doesn't need the timeout to expire.
Of course one the thread is awaken it must be able to handle the "exceptional" condition of continuing even if the "main" handle it was waiting for didn't return in time.

Are aysnchronous NSURLConnections multi-threaded

I've noticed that if I create an NSURLConnection and fire the request, all is well. My delegate methods get called and the last delegate method get's called well after the code block invoking the connection completes. Great.
That leads me to believe the connections are asynchronous which implies that they're multi-threaded. Is that correct? Could they be asynchronous but in the same thread? No, that's crazy - right?
But, in every example I've seen using an NSOperation, NSURLConnections are always scheduledInRunLoop after which [runLoop runMode ...] is invoked in a while loop.
Can someone explain exactly what is happening here? It seems to me that the first case requires spawning secondary threads but no manual invocation of the run loop (on those threads) while NSOperation (in a new thread) does require manual invocation of the run loop.
Why is no manual invocation required for the first case?
NSURLConnection does spawn a single background thread to manage all instances of itself, but this is generally irrelevant to the caller, since the delegate calls are made on whatever thread owns the runloop the connection was scheduled in. (This fact turned out to be very relevant to me recently, but these things really only come up when dealing with insane crashers in multi-threaded apps.)
For more caller-relevant details, you should look at the docs for -[NSURLConnection scheduleInRunLoop:forMode:]. It explains how to manually handle scheduling and unscheduling, and how NSURLConnections behave in a multi-threaded environment.
If you are unclear on how run loops work and how they perform asynchronous actions without requiring additional threads, you should read Run Loops in the Threading Programming Guide. This is a very important topic for moving to more advanced Cocoa development.
Because the main thread already has a run loop, I'd imagine.
If you want to run NSURLConnection in another thread, you should create a run loop like this in your thread's main method:
while (!finished)
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}

Resources