Issue using Task.Factory.FromAsync - c#

I enjoyed the new C# 5's async and await and I want to set it up to one of my previous Tcp application which I used the async whay (not async & await, in fact Begin*, End*)
in my application every message have a response, so every time you use BeginSend, you will receive a message related the message you first sent. (lets suppose command and it's report)
I want to add a new function called RequestAsync that you send your message and wait till the response comes. let me show the usage
string response = await RequestAsync("hi");
on this occasion, you will send a "hi" message and then code waits till the response related to this comes.
I had problems using Task.Factory.FromAsync, so I tried the following code, i want to make sure the performance is roughly the same as TaskFactory way.
public async Task<IRequestResult> SendRequestAsync(IRequest request, string message)
{
IRequestResult result = BeginSendRequest(request, message);
while (!result.IsCompleted)
{
await Task.Delay(1);
}
return result;
}
and BeginRequest is my own method.
Sincerely yours,
Peyman Mortazavi

No, that's going to be pretty awful in terms of efficiency - you'll be waking up and requiring rescheduling every 5 milliseconds. You've added latency while you effectively sleep between cycles as well.
You should go back to trying to use Task.Factory.FromAsync - you haven't told us what went wrong when you tried that, so it's hard to help you fix it... It's possible that you haven't implemented the asynchronous programming model pattern correctly to start with. (The fact that you're not providing a callback to your BeginSendRequest method is suggestive of that.)
I hope your real code doesn't have catch {} either...

Poling can never be efficient as IO completion ports, and why even use an async method if you are only waiting for it and not doing anything in the mean time, it just ads needles overhead.

Related

Can a aspnetcore api controller "lose" tasks run without await?

I'm getting a little lost between processes, threads etc.
Essentially, I'm just trying to find a standard way of doing something on an incoming request, that might take 5-300 seconds without the client having to wait that long for a response.
Given the code below, can any of the numbered ways of calling the long running method be swallowed?
As in, can this ever happen?
Enter endpoint (second 0)
Start long running task
Return response (second 2)
At second 2? 5? 30? this... instance/thread/call/execution environment just shuts down because its "done". I'm "done" because my response is sent.
OR is the long running task itself keeping the... instance/thread/call alive? Or is an api just always alive?
public async Task<ActionResult<int>> Get()
{
// second 0
//...
var threadId = Thread.CurrentThread.ManagedThreadId;
DoSomething60sAsync(); // #1 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
_ = DoSomething60sAsync(); // #2 No Warning
Task.Run(DoSomething60sAsync); // #3 Same Warning as #1
_ = Task.Run(DoSomething60sAsync); // # 4 No Warning
return Ok(threadId); // second 2
}
private async Task DoSomething60sAsync()
{
for (int i = 0; i < 60; i++)
{
var threadId = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine(threadId + ": Second " + i);
await Task.Delay(1000);
}
}
As you can see, I tried to look at the threads. I noticed they're ALL background threads. I also noticed that the threadId seems completely random. It even changes within that for loop.
I read that aspnetcore threading is complicated.
Given that they're all background threads anyway, using Task.Run in #3/#4 seems pointless.
Another way of solving this problem I read about is implementing a IHostedService and some kind of TaskRunner-BackgroundQueue. https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio
Also there is Hangfire.
I tried all of these and they all seem to work. So I would like to use the simplest solution, but I'm worried that just "calling tasks without await" will be lost somehow. Is this a valid concern? Can this ever happen?
Essentially, I'm just trying to find a standard way of doing something on an incoming request, that might take 5-300 seconds without the client having to wait that long for a response.
There are a few names for this. I've called it "basic distributed architecture", but "asynchronous messaging" is also common. The core idea is that you need two things:
A durable queue.
A backend process.
At second 2? 5? 30? this... instance/thread/call/execution environment just shuts down because its "done". I'm "done" because my response is sent.
OR is the long running task itself keeping the... instance/thread/call alive? Or is an api just always alive?
Loss of work is certainly possible. Shutdowns are normal, and when the hosting process is shut down, work can be lost.
Given that they're all background threads anyway, using Task.Run in #3/#4 seems pointless.
On ASP.NET Core, yes, that is true. Also, the discard (_ = ) is literally just telling the compiler "I know what I'm doing; don't give me a warning", so you're not getting a warning on those lines because the warning is silenced - the code is still just as dangerous (i.e., you'll still lose work).
Another way of solving this problem I read about is implementing a IHostedService and some kind of TaskRunner-BackgroundQueue.
To prevent loss of work, your queue has to be durable (saved on disk).
Also there is Hangfire.
Hangfire (or an IHostedService connected to a durable queue) is one way to implement asynchronous messaging. I tend to prefer background services in separate processes for reasons described on my blog, but a background service inside the ASP.NET Core process would also work.

Does async (one task) make sense in MVC?

I am using async/await in MVC, but only when I have more than one task (WaitAll).
I understand that having only one task is good to have the UI free, in case of WPF or Windows Form, but does it make sense for MVC to have only one task and await for that?
I've seen it a lot in code, in MVC, but I don't get the advantages.
HTTP requests are handled by thread pool threads.
If you block a thread, it will not be able to do other work. Because the total number of threads is limited, this can led to the starvation of the thread pool and new requests will be denied - 503.
Using async code, the thread is released back to the thread pool, becoming available to handle new requests or the continuations of async code.
Like on client UIs, on the server, async code is all about responsiveness, not performance. Requests will take longer but your server will be able to handle more requests.
It depends on what you are trying to achieve. For instance, if you have multiple calls to multiple services you can always do it in a way that only the last call makes the rest of the system "wait".
You can optimise your code in a way that X asynchronously calls to services start (almost) at the same time without having to 'await' for one another.
public async Task RunSomethings()
{
var something1 = AsyncCall1();
var something2 = AsyncCall2();
var something3 = await AsyncCall3();
}
private async Task<Something1> AsyncCall1()
{
return await Something1();
}
private async Task<Something2> AsyncCall2()
{
return await Something2();
}
private async Task<Something3> AsyncCall3()
{
return await Something3();
}
I hope it helps.
Good question. Using asynchronous methods is all about using the resources effectively as well as give a good user experience. Any time you need to call on a resource that could take time to collect, it's good to use an async call.
This will do a few things. First, while a worker thread is waiting for data, it can be put on 'hold' so to speak, and that worker thread can do something else until the data is returned, an error is returned or the call just times out.
This will give you the second advantage. The interface the user is using to call the resource will be released, temporarily, to do other things. And overall, less server resources are consumed by idle processes.
I'd recommend watching the videos on this page here: https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async
It's probably the clearest explanation that can help leapfrog your learning on async.

Use async/ await or something else

I'm writing a program that communicates with some control hardware that I've designed. The hardware is driving motors and the first thing I'm trying to do with it is to initialize a motor.
The hardware is comm controlled, so to do anything I simply send a message out through USB to the hardware.
To initialize a motor I have to send 2 messages; after I send the first one it moves the motor toward a sensor, and when it reaaches it it stops and sends a message back to me telling me that it has stopped, at which point I send it another message telling it to drive the motor in the opposite direction very slowly until it comes out of the sensor.
All of my comms reception is in a SerialPort DataReceived event. What is the best way that I can wait for the relevant message and then send the second message? At the moment I'm simply using a property of type bool which I set to true just before initialization, and then in my event handler if I receive the message telling me that the motor has stopped and the bool is true, I set the bool to false and send the second message. While this works I was thinking that it might be possible to use async and await? And that this might be a little more efficient in general? Or is there another approach that I could take that would be better?
Any feedback/ guidance will be greatly appreciated!
In my opinion, the nice thing about async-await is not that it keeps your caller responsive, but your code looks easier, almost as if it was not async-await.
Keeping your caller responsive can also be accomplished using Tasks and ContinueWith statements, or by using a Backgroundworker or other methods to create a thread. But if you use async await, you don't have to remember the state of your progress, something you do now by setting the boolean.
Your code would look like this:
public Task InitializeAsync(...)
{
await Send1stMessageAsync();
await Send2ndMessageAsync();
}
In this article Eric Lippert explained async-await using a kitchen metaphor. What happens is that your thread will do everything to send the 1st message until it can't do anything anymore but wait for the reply. Control is then given to the first caller who is not awaiting. That would have been you if you weren't awaiting, for instance if you had the following code:
public Task InitializeAsync(...)
{
var task1stMessage = Send1stMessageAsync();
// this thread will do everything inside Send1stMessageAsync until it sees an await.
// it then returns control to this function until there is an await here:
DoSomeThingElse();
// after a while you don't have anything else to do,
// so you wait until your first messages has been sent
// and the reply received:
await task1stMessage;
// control is given back to your caller who might have something
// useful to do until he awaits and control is given to his caller etc.
// when the await inside Send1stMessageAync is completed, the next statements inside
// Send1stMessageAsync are executed until the next await, or until the function completes.
var task2ndMessage = Send2ndMessageAsync();
DoSomethingUseful();
await task2ndMessage;
}
You wrote that you use events to notify your thread that the data has been received. Although it is not difficult to make your Send1stMessageAsync an async function, you don't have to reinvent the wheel. Consider using a nuget package like SerialPortStream to get async functions that send messages and wait for reply.
I you are waiting for something to happed and you don't have event handler at your disposal it would be a good idea to use async/await pattern
async Task WaitForCompletion()
{
await Task.Run(()=>
{
while(!theBoolVar)
Thread.Sleep(1000);
});
}
and then just in your code use
await WaitForCompletion();

Recursively call async method vs long running task when receiving data from TcpClient

I'm currently rewriting my TCP server from using StreamSocketListener to TcpListener because I need to be able to use SSL. Since it was some time ago that I wrote the code I'm also trying to make it more cleaner and easier to read and hopefully increase the performance with higher number of clients but I'm currently stuck.
I'm calling a receive method recursively until the client disconnects but I'm starting to wonder if it wouldn't be a better to use a single long running task for it. But I hesitate to use it since it will then create a new long running task for every connected client. That's why I'm turning to the Stack Overflow community for some guidance on how to proceed.
Note: The connection is supposed to be open 24/7 or as much as possible for most of the connected clients.
Any comments are appreciated.
The current code looks something like this:
private async Task ReceiveData(SocketStream socket) {
await Task.Yield();
try {
using (var reader = new DataReader(socket.InputStream)) {
uint received;
do {
received = await reader.LoadAsync(4);
if (received == 0) return;
} while (reader.UnconsumedBufferLength < 4);
if (received == 0) return;
var length = reader.ReadUInt32();
do {
received = await reader.LoadAsync(length);
if (received == 0) return;
} while (reader.UnconsumedBufferLength < length);
if (received == 0) return;
// Publish the data asynchronously using an event aggregator
Console.WriteLine(reader.ReadString(length));
}
ReceiveData(socket);
}
catch (IOException ex) {
// Client probably disconnected. Can check hresult to be sure.
}
catch (Exception ex) {
Console.WriteLine(ex);
}
}
But I'm wondering if I should use something like the following code instead and start it as a long running task:
// Not sure about this part, never used Factory.StartNew before.
Task.Factory.StartNew(async delegate { await ReceiveData(_socket); }, TaskCreationOptions.LongRunning);
private async Task ReceiveData(SocketStream socket) {
try {
using (var reader = new DataReader(socket.InputStream)) {
while (true) {
uint received;
do {
received = await reader.LoadAsync(4);
if (received == 0) break;
} while (reader.UnconsumedBufferLength < 4);
if (received == 0) break;
var length = reader.ReadUInt32();
do {
received = await reader.LoadAsync(length);
if (received == 0) break;
} while (reader.UnconsumedBufferLength < length);
if (received == 0) break;
// Publish the data asynchronously using an event aggregator
Console.WriteLine(reader.ReadString(length));
}
}
// Client disconnected.
}
catch (IOException ex) {
// Client probably disconnected. Can check hresult to be sure.
}
catch (Exception ex) {
Console.WriteLine(ex);
}
}
In the first, over-simplified version of the code that was posted, the "recursive" approach had no exception handling. That in and of itself would be enough to disqualify it. However, in your updated code example it's clear that you are catching exceptions in the async method itself; thus the method is not expected to throw any exceptions, and so failing to await the method call is much less of a concern.
So, what else can we use to compare and contrast the two options?
You wrote:
I'm also trying to make it more cleaner and easier to read
While the first version is not really recursive, in the sense that each call to itself would increase the depth of the stack, it does share some of the readability and maintainability issues with true recursive methods. For experienced programmers, comprehending such a method may not be hard, but it will at the very least slow down the inexperienced, if not make them scratch their heads for awhile.
So there's that. It seems like a significant disadvantage, given the stated goals.
So what about the second option, about which you wrote:
…it will then create a new long running task for every connected client
This is an incorrect understanding of how that would work.
Without delving too deeply into how async methods work, the basic behavior is that an async method will in fact return at each use of await (ignoring for a moment the possibility of operations that complete synchronously…the assumption is that the typical case is asynchronous completions).
This means that the task you initiate with this line of code:
Task.Factory.StartNew(
async delegate { await ReceiveData(_socket); },
TaskCreationOptions.LongRunning);
…lives only long enough to reach the first await in the ReceiveData() method. At that point, the method returns and the task which was started terminates (either allowing the thread to terminate completely, or to be returned to the thread pool, depending on how the task scheduler decided to run the task).
There is no "long running task" for every connected client, at least not in the sense of there being a thread being used up. (In some sense, there is since of course there's a Task object involved. But that's just as true for the "recursive" approach as it is for the looping approach.)
So, that's the technical comparison. Of course, it's up to you to decide what the implications are for your own code. But I'll offer my own opinion anyway…
For me, the second approach is significantly more readable. And it is specifically because of the way async and await were designed and why they were designed. That is, this feature in C# is specifically there to allow asynchronous code to be implemented in a way that reads almost exactly like regular synchronous code. And in fact, this is borne out by the false impression that there is a "long running task" dedicated to each connection.
Prior to the async/await feature, the correct way to write a scalable networking implementation would have been to use one of the APIs from the "Asynchronous Programming Model". In this model, the IOCP thread pool is used to service I/O completions, such that a small number of threads can monitor and respond to a very large number of connections.
The underlying implementation details actually do not change when switching over to the new async/await syntax. The process still uses a small number of IOCP thread pool threads to handle the I/O completions as they occur.
The difference is that the when using async/await, the code looks like the kind of code that one would write if using a single thread for each connection (hence the misunderstanding of how this code actually works). It's just a big loop, with all the necessary handling in one place, and without the need for different code to initiate an I/O operation and to complete one (i.e. the call to Begin...() and later to End...()).
And to me, that is the beauty of async/await, and why the first version of your code is inferior to the second. The first fails to take advantage of what makes async/await actually useful and beneficial to code. The second takes full advantage of that.
Beauty is, of course, in the eye of the beholder. And to at least a limited extent, the same thing can be said of readability and maintainability. But given your stated goal of making the code "cleaner and easier to read", it seems to me that the second version of your code serves that purpose best.
Assuming the code is correct now, it will be easier for you to read (and remember, it's not just you today that needs to read it…you want it readable for the "you" a year from now, after you haven't seen the code for awhile). And if it turns out the code is not correct now, the simpler second version will be easier to read, debug, and fix.
The two versions are in fact almost identical. In that respect, it almost doesn't matter. But less code is always better. The first version has two extra method calls and dangling awaitable operations, while the second replaces those with a simple while loop. I know which one I find more readable. :)
Related questions/useful additional reading:
Long Running Blocking Methods. Difference between Blocking, Sleeping, Begin/End and Async
Is async recursion safe in C# (async ctp/.net 4.5)?

Calling an async method from the browser

From my understanding when we use await and the awaited task is not yet completed then the execution returns to caller. It works fine in server side(calling the async method from server side method itself). But what happends when I call from UI to an async method.
public class TestController : ApiController
{
IList<string> lstString = new List<string>();
public async Task<IList<string>> GetMyCollectionAsync()
{
lstString.Add("First");
string secString = await GetSecondString(); // I am expecting a response back to UI from here.
lstString.Add(secString);
lstString.Add("Third");
return lstString;
}
private async Task<string> GetSecondString()
{
await Task.Delay(5000);
return "Second after await";
}
}
I tested with the above API from browser like
http://localhost:port/Test
, but I got response only after 5 sec in my UI.
Am I thinking it wrongly?
Am I thinking it wrongly?
Yes. async-await does not change the nature of the HTTP protocol, which is of type request-response. When using async-await inside an ASP.NET controller, using an async method will not yield a response to the caller, it would only yield the requests thread back to the threadpool.
But if this is true, then using async method having a single await in controller side is not useful. right? because it took the same time of synchronous call
Async shines when you need scalability. It isn't about "yield this response as fast as possible", it's about being able to handle a large amount of requests without exhausting the thread-pool. Once the thread starts executing IO work, instead of being blocked, it is returned. Thus, able to serve more requests.
Async by itself does not make anything "go faster", which is a conception I see people thinking alot. If you're not going to be hitting your web service with many concurrent requests, you're most likely not going to be seeing any benefit from using it. As #Scott points out, an async method has a slight overhead as it generates a state machine behind the scenes.
async/await allow the thread to go off servicing other requests while there is that idle 5 seconds, but ultimately everything in GetMyCollectionAsync has to complete before a response is sent to the client.
So I'd expect your code to take 5 seconds and return all 3 strings in the response.

Categories

Resources