Output of one Task input to other Task - c#

In Winforms, I have following: ProcessClientAsync adds an element to a ConcurrentDictionary. How can I ensure that the forloop runs after the Task.Run(). I tried to remove ConfigureAwait but it freezes the UI.
public async Task Listen(int port)
{
try
{
IPAddress serverAddress = IPAddress.Parse("127.0.0.1"); // localhost
_listener = new TcpListener(serverAddress, port);
_listener.Start();
while (true)
{
TcpClient tcpClient = await _listener.AcceptTcpClientAsync();
await Task.Run(() => ProcessTcpClientAsync(tcpClient).ConfigureAwait(false));
_statusText.StatusUpdate = "number of users are " + _mapClient.GetUsers().Count;
}
}
catch (SocketException ex)
{
string message = string.Format("Error listening on port {0}. Make sure IIS or another application is not running and consuming your port.", port);
throw new Exception(message, ex);
}
}
private async Task<string> ProcessTcpClientAsync(TcpClient tcpClient)
{
string key = string.Empty;
WebSocket webSocket = null;
try
{
if (_isDisposed)
return string.Empty;
// this worker thread stays alive until either of the following happens:
// Client sends a close conection request OR
// An unhandled exception is thrown OR
// The server is disposed
// get a secure or insecure stream
NetworkStream stream = tcpClient.GetStream();
WebSocketHttpContext context = await _webSocketServerFactory.ReadHttpHeaderFromStreamAsync(stream);
if (context.IsWebSocketRequest)
{
key = GetKeyFromContext(context);
// _statusText.StatusUpdate = "Connection from origin.";
webSocket = await _webSocketServerFactory.AcceptWebSocketAsync(context);
//_statusText.StatusUpdate = "Connection accepted.";
await RespondToWebSocketRequestAsync(tcpClient, key, webSocket);
}
else
{
//_statusText.StatusUpdate = "Http header contains no web socket upgrade request. Ignoring...";
}
}
catch (Exception ex)
{
}
finally
{
try
{
await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Closed in server by the client", CancellationToken.None);
tcpClient.Client.Close();
tcpClient.Close();
}
catch (Exception ex)
{
}
}
return key;
}

You could await the Task.Run, but make sure to make the parent method async
await Task.Run(() => ProcessClientAsync(client).ConfigureAwait(false));
This will wait for the async task to complete, and then execute the rest of the code. I would suggest learning a bit more about async/await.

To block the ProcessClientAsync call you can do the following:
Task.Run(() => ProcessClientAsync(client)).Wait();
If you want to access the result of ProcessClientAsync:
Task<TResult> task = null;
Task.Run(() => task = ProcessClientAsync(client)).Wait();
// task.Result contains the result
Even if this works, it's recommended to await tasks rather than blocking with wait.

Quiz, what is the type of the variable x below?
var x = Task.Run(() => Task.Delay(1000).ConfigureAwait(false));
The type is not Task. It is Task<ConfiguredTaskAwaitable>. That internal ConfigureAwait(false) call is not only meaningless, but it also created a
unexpected situation where the return value must now be awaited twice:
await await x;
Don't do this. If you have to use ConfigureAwait(false) for some reason, then you are expected to await the result immediately. Don't pass ConfiguredTaskAwaitable structs around. My advice is to search your code for more instances of this anti-pattern, and eliminate them.

If you don't want to mark the parent method as async, then you could use the following instead:
Task.Wait(Task.Run(() => ProcessClientAsync(client)));
This method has several overloads that allow for configurability of cancellation and timeouts as well:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.wait?view=netframework-4.8
Also, if your code actually says while (true) and has no break conditions, then it will never exit.

Related

What's the best way to establish and validate a connection from a client without blocking?

I have a TcpListener server that can open a connection with a client by calling server.AcceptTcpClientAsync(). Unfortunately, there is random, unwanted traffic connecting to the server that I don't care about, so I've added a method, Task<bool> Handshake(TcpClient client), to validate that the client should be able to talk to the server.
The naive way to get a connection is:
async Task<TcpClient> GetClient(TcpListener server)
{
while (true)
{
var client = await server.AcceptTcpClientAsync();
if (await Handshake(client))
{
return client;
}
client.Dispose();
}
}
Unfortunately, the handshake process takes a nonzero amount of time to timeout when waiting on a spurious connection, and if it takes longer than it takes for the next connection to show up, pending connections will stack up and never get serviced.
I know that APIs like Task.WhenAny allow for multiple async operations to be running at once, but I can't seem to get a proper model for this connection process worked out.
What I want:
Only one successful connection is expected.
When a connection arrives, attempt a handshake. If the handshake is successful, return it and dispose any other pending connections. If not, dispose the connection.
A handshake being in progress should not prevent the loop from accepting a new connection.
It's always possible for the number of handshakes in progress to be 0, 1, or more than 1.
Is there any good way to express this in code?
You can use Channel for safe cross thread communication
var channel = Channel.CreateBounded<TcpClient>(100);
var writer = channel.Writer;
var reader = channel.Reader;
_ = GetClient(server);
var successClient = await Task.Run(async () =>
{
await foreach (var client in reader.ReadAllAsync())
{
if (await Handshake(client))
{
return client;
}
client.Dispose();
}
return null;
});
//mark the channel that no more data is going to be written to it
writer.TryComplete();
//run through the remaining clients in the channel and dispose of them
await foreach (var client in reader.ReadAllAsync())
{
client.Dispose();
}
//use successClient here
async Task<TcpClient> GetClient(TcpListener server)
{
while (true)
{
var client = await server.AcceptTcpClientAsync();
await writer.WriteAsync(client);
}
}
To begin, you can use Task.Run to execute the task so that you don't have to await there. Then you can use ContinueWith as a callback to handle successful handshake. Next, You can maintain a list of connections, to be disposed.
Also, I would suggest adding some delay while looping,
async Task<TcpClient> GetClient(TcpListener server)
{
List<Task<Client>> _clients=new();
bool handshakeCompleted=false;
Client workingClient=null;
while (!handshakeCompleted)
{
var client = Task.Run(async ()=> await server.AcceptTcpClientAsync());
client.ContinueWith(async ()=>
{
if (await Handshake(client))
{
handshakeCompleted=true;
workingClient=client;
}
});
_clients.Add(client);
await Task.Delay(10);
}
foreach(var c in _clients.Where(c!=workingClient)) c.Dispose();
return workingClient;
}

client.GetStreamAsync(url) is freezing my UI

So I'm listening to an Server side event with my code to just write it on the console (for now) but it seems that this is making my window's form UI freeze
The code in question (which I'm calling from the main form's function)
static async Task hello()
{
HttpClient client = new HttpClient();
//client.Timeout = TimeSpan.FromSeconds(5);
while (true)
{
try
{
Console.WriteLine("Establishing connection");
using (var streamReader = new StreamReader(await client.GetStreamAsync(url)))
{
while (!streamReader.EndOfStream)
{
var message = await streamReader.ReadLineAsync();
Console.WriteLine(message.ToString());
}
}
}
catch (Exception ex)
{
//Here you can check for
//specific types of errors before continuing
//Since this is a simple example, i'm always going to retry
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine("Retrying in 5 seconds");
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
}
Thanks in advance
I've solved the problem, it appears that async/await task freezes the GUI. To stop this from happening you need to use Task.Run(() => your_function()); when you call an async function
This question might be a possible duplicate of: GUI freezes when using async/await ... so go there if you want to find a bit more knowledge about the subject

C# - Does calling Task.Result wait until result is returned before returning

Here is my code:
public void ConnectToWorldServer()
{
if (socketReady)
{
return;
}
//Default host and port values;
string host = ClientWorldServer.ServerIP;
int port = ClientWorldServer.TCPPort;
//ClientLoginServer ClientLoginServer = new ClientLoginServer();
try
{
socket = new TcpClient(host, port);
stream = socket.GetStream();
socket.NoDelay = true;
writer = new StreamWriter(stream);
reader = new StreamReader(stream);
socketReady = true;
//Preserve the connection to worldserver thrue scenes
UnityThread.executeInUpdate(() =>
{
DontDestroyOnLoad(worldserverConnection);
});
// Start listening for connections.
while (true)
{
if (socketReady)
{
if (stream.DataAvailable)
{
string sdata = reader.ReadLine();
if (sdata != null)
{
Task<JsonData> jsonConvert = Task<JsonData>.Factory.StartNew(() => convertJson(sdata));
UnityThread.executeInUpdate(() =>
{
OnIncomingData(jsonConvert.Result);
});
}
}
}
}
}
catch (Exception e)
{
Debug.Log("Socket error : " + e.Message);
}
}
private JsonData convertJson(string data)
{
return JsonConvert.DeserializeObject<JsonData>(data);
}
What I am wondering now is does this part of the code:
UnityThread.executeInUpdate(() =>
{
OnIncomingData(jsonConvert.Result);
});
block until this task returns back a result:
Task<JsonData> jsonConvert = Task<JsonData>.Factory.StartNew(() => convertJson(sdata));
I am really not that familiar with Tasks. My goal is to run the json conversion and then execute OnIncomingData(jsonConvert.Result);.
I think my code is not doing that. Why?
When a thread invokes Task.Result it will block until the Task completes, either by returning a value, throwing an exception, or being canceled. From the documentation:
Accessing the property's get accessor blocks the calling thread until the asynchronous operation is complete; it is equivalent to calling the Wait method.
So, to be clear, calling Task<JsonData>.Factory.StartNew creates a Task (which represents some computation to be executed), and schedules it for execution (when it gets executed and on what thread is up to the default TaskScheduler, but StartNew should return immediately). Your call to UnityThread.executeInUpdate will then happen without waiting for the Task you created to complete. At the point where UnityThread calls the anonymous function you passed to executeInUpdate that thread will block until the Task completes. I'm not familiar with UnityThread.executeInUpdate so I cannot tell you whether it will block until that callback completes or not.
One thing to be aware of is that depending on how Unity works with threads, it is possible to create a deadlock by accessing the Result property. In some cases a Task will attempt to use a specific context to execute, and if you cause that context to block waiting for the Task to complete, it will never get a chance to run: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
If you want to wait for the result then what is the point of using the Task. The right way of doing thing asynchronously is making your function async all the way.
public async void ConnectToWorldServer()
{
.....
.....
// Here await will put this method call on a queue to finish later and will return from this method.
Task<JsonData> jsonConvert = await Task<JsonData>.Factory.StartNew(() => convertJson(sdata));
// After the task is finished, it will resume to this method here to execute next statement.
UnityThread.executeInUpdate(() =>
{
OnIncomingData(jsonConvert.Result);
});
.....
.....
}

.NET - Socket server with async/await

I'm writing simple socket server with C#. The idea is to do it as simple as possible since the communication won't be heavy. I've used some of the TAP/APM patterns on socket async calls so the code now looks like this:
public async Task StartListening()
{
try
{
var endpoint = new IPEndPoint(IPAddress.Loopback, Port);
using (Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
Socket.Bind(endpoint);
Socket.Listen(Limit);
while (!Shutdown)
{
// await till we get the connection - let the main thread/caller continue (I expect this loop to continue in separate thread after await)
var socket = await Socket.AcceptAsync().ConfigureAwait(false);
var state= new ClientStateObject(socket, id);
// do not await for receive - continue to listen for connections
Receive(socket, state);
}
}
}
catch (Exception ex)
{
// handle errors via callbacks
}
}
private async void Receive(Socket socket, ClientStateObject state)
{
try
{
while (!Shutdown)
{
var bytes = await socket.ReceiveAsync(state).ConfigureAwait(false);
var readResult = state.Read(bytes);
if (readResult == CloseConn)
{
// close connection
return;
}
if (readResult == Completed)
{
// process the message
state.Reset();
}
}
}
catch (Exception ex)
{
// handle errors via callbacks
}
}
This code seems to run fine in development builds, but sometimes behaves strange in release mode. I assume this might be related to race conditions or something that is related to threading and async/await. Does anyone see what might be the problem with the above code?
Just to be clear AcceptAsync/ReceiveAsync are wrappers around socket methods to return tasks.

Async/await and WebException handling

I am struggling around the (seems so) pretty famous problem of the exception handling by using the async/await pattern. Specifically my context is on a HTTP client, but I have also tried with a much simpler test, and it behaves the same.
Consider the below program, which is a super-simplified version of my original app's context.
class Program
{
static void Main(string[] args)
{
Test();
Console.Write("Press any key...");
Console.ReadKey();
Console.WriteLine();
}
static async void Test()
{
var c = new MyClient();
try
{
var uri = new Uri("http://www.google.com/"); //valid address
var s = await c.GetString(uri);
Console.WriteLine(s.Length);
}
catch (WebException ex)
{
Console.WriteLine(ex.Message);
}
try
{
var uri = new Uri("http://www.foo.bah/"); //non-existent address
var s = await c.GetString(uri);
Console.WriteLine(s.Length);
}
catch (WebException ex)
{
Console.WriteLine(ex.Message);
}
}
}
class MyClient
{
public async Task<string> GetString(Uri uri)
{
var client = new HttpClient();
return await client.GetStringAsync(uri);
}
}
When the program starts, it downloads the first web site's page as a string, then displays its length: that's fine. Afterward, when the same operation is performed against an invalid address, the client raises a WebException (that's what I want), but it's not caught.
UPDATE: as "not caught", I mean that the code actually does not flow through the "catch" branch and silently displays the exception message. Instead, the exception is shown by the VS IDE, and the debugging breaks.
Any decent solution to catch the exception?
Many thanks in advance.
Although you have already figured out the exception is HttpRequestException not WebException, still I would like to highlight few important things about async-await operator usage.
async void is of type fire & forget and is only & only for event handlers.
As soon as compiler reaches first await operator inside async method control returns to the caller.
Debugging your code :-
Since you are using async void in Test method so the control returns to the caller and execution continues to line Console.Write("Press any key..."); without having any information about the Task and then you are waiting for the user input.
In the meanwhile response from awaited method comes and the execution continues inside Test method.
If you comment out the line Console.ReadKey(); inside main() OR user provides input immediately then you'll notice that response may or may not get printed. This is because you are not waiting on the Task getting executed you simply trusted on the user that he will not enter anything till your Task completes.
Solution:-
Solution is to return Task from Test() and then wait till it finishes, below is the updated code also note adding Async at the end of method name is the naming convention you must follow to save you from the headache of distinguishing between asynchronous and synchronous methods.
class Program
{
static void Main(string[] args)
{
Task task = TestAsync();
Console.Write("Press any key...");
task.wait();
//Console.ReadKey();
Console.WriteLine();
}
static async Task<string> TestAsync()
{
var c = new MyClient();
try
{
var uri = new Uri("http://www.google.com/"); //valid address
var s = await c.GetStringAsync(uri);
Console.WriteLine(s.Length);
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.Message);
}
try
{
var uri = new Uri("http://www.foo.bah/"); //non-existent address
var s = await c.GetStringAsync(uri);
Console.WriteLine(s.Length);
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.Message);
}
//to avoid compiler error
return null;
}
}
class MyClient
{
public async Task<string> GetStringAsync(Uri uri)
{
var client = new HttpClient();
return await client.GetStringAsync(uri);
}
}

Categories