I have to write a simple client for a chat server, and I want to concurrently check input from the console and from the socket connected to the server. Here is the desired behavior in C, and I want to replicate this behavior in C#:
while (true) {
//make set of descriptors
fd_set reads;
FD_ZERO(&reads);
FD_SET(client_socket, &reads);
FD_SET(0, &reads);
select(client_socket+1, &reads, NULL, NULL, NULL);
//handle user input from stdin
if (FD_ISSET(0, &reads)) {
///
}
//handle message from server
if (FD_ISSET(client_socket, &reads)) {
///
}
}
I came up with this solution in C#, but I'm not sure if it is valild or efficient. Are there any other approaches?:
var ongoingTasks = new List<Task> {getServerMsg, getUserMsg};
while (true)
{
var finishedTask = await Task.WhenAny(ongoingTasks);
if (finishedTask == getServerMsg) {
OutputServerMsg();
ongoingTasks.Remove(getServerMsg);
getServerMsg = ReceiveMessageFromServer();
ongoingTasks.Add(getServerMsg);
} else if (finishedTask == getUserInput) {
SendMsgToServer();
ongoingTasks.Remove(getUserInput);
getUserInput = ReceiveInputFromStdIn();
ongoingTasks.Add(getUserInput);
}
}
Are you looking at synchronous or asynchronous operations? anyway here is the async version, your solution looks too simple
ReceiveDataAsync listens for data from the server. It uses Socket.ReceiveAsync for receiving data from the server asynchronously.
ReadUserInputAsync waits for user input in the console using Task.Run to run synchronously blocking operations (Console.ReadLine()) on a separate thread, enabling the main thread to remain responsive.
Task.WhenAny is used to await either of the tasks to complete. This approach keeps the UI responsive (if there's one) and doesn't block the main thread.