-1

im starting using async taks to create the simulation of a client and server responses, i made it work but now i want to have more control over the messages that every client sends, i got it by making a custom printLine to print in the console with colors and tags, but now, because the server and client runs asynchronously the messagges on the console overlaps:

[Server]>       Wating for a conection...
[Client #0]>    [Client #1]>    Socket connected to -> [SomeIP]:11111
Socket connected to -> [SomeIP]:11111
[Server]>       Text received -> Test Client<EOF>
[Client #1]>    Message from server -> Test Server
[Server]>       Wating for a conection...
[Server]>       Text received -> Test Client<EOF>
[Client #0]>    [Server]>       Message from server -> Test Server

This is because my own printLine method is executed not in a single line of code, how can i do to run this method synchronously to wait until the execution completition of this method? Thanks and sorry for my english.

This is the method that runs the taks:

    static async Task Start(){
        Server.Server server = new Server.Server();
        Client.Client client0 = new Client.Client(0);
        Client.Client client1 = new Client.Client(1);

        var serverTask = Task.Run(() => server.ExecuteServer());
        var clientTask0 = Task.Run(() => client0.ExecuteClient());
        var clientTask1 = Task.Run(() => client1.ExecuteClient());

        await clientTask1;
        await clientTask0;
        Console.WriteLine("Done");
    }

and this is my ownn PrintLine method

    void printLine(string line){
        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.Write("[Client #" + clientID + "]>\t");
        Console.ResetColor();
        Console.WriteLine(line + "\n");
    }
Farengar
  • 33
  • 8
  • 3
    `printLine("whatever");` will execute it synchronously. Perhaps use a `lock` around your blocks of code that interact with `Console` so that only one can execute at once (so they get the colour they expect etc). – mjwills May 06 '20 at 04:27
  • C# and .NET provide a plethora of mechanisms to ensure mutual exclusion for resources or sections of code. See marked duplicate, for many examples of these – Peter Duniho May 06 '20 at 06:53

2 Answers2

0

Use a lock, to serialise the execution of your print code

The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.

private readonly object _sync = new object();

void printLine(string line)
{
    lock (_sync)
    {
        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.Write("[Client #" + clientID + "]>\t");
        Console.ResetColor();
        Console.WriteLine(line + "\n");
    }
}
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
-1

As said in comments, your concern here is not about synchronous / asynchronous only, but also about concurrent ressources access.

As you are using tasks, they are handled by different threads of a threadpool that you can’t control directly.

As suggested once again in the comments of your question, you can wrap all the prints statements in a controlled manner using a mutex for instance.

1) the task’s thread acquires the mutex (or waits for it)

2) the task’s thread prints all the statements

3) the task’s thread releases the mutex

Be sure that the main thread, before starting the tasks, creates the mutex and releases it before tasks starts. In the constructor you can specify if you want the current thread owning the mutex (false in your case).

glihm
  • 1,138
  • 13
  • 29