0

I want to create an IRC connection but I was having trouble because the connection was not using ConnectAsync. It is now using ConnectAsync but the UI is still blocked.

I would appreciate it if someone can help me with working example code for a non-blocking IRC connection that I can read/write from/to as I am struggling to understand asynchronous code.

async Task Connect()
{
    using (var client = new TcpClient())
    {
        await client.ConnectAsync("127.0.0.1", 1234);

        using (var stream = client.GetStream())
        using (var writer = new StreamWriter(stream))
        using (var reader = new StreamReader(stream))
        {
            writer.AutoFlush = true;

            writer.WriteLine("USER Test 0 * :Test");
            writer.WriteLine("NICK Test");

            while (client.Connected)
            {
                var data = reader.ReadLine();

                if (data != null)
                {
                    var d = data.Split(' ');

                    textBox1.AppendText($"Data: {data}" + Environment.NewLine);

                    if (d[0] == "PING")
                    {
                        writer.WriteLine("PONG");
                    }
                }
            }
        }
    }
}

private void button1_Click(object sender, EventArgs e)
{
    Connect();
}
  • Have you tried using `WriteLineAsync` and `ReadLineAsync` instead? – Xerillio Sep 26 '20 at 13:05
  • You mean `private async void button1_Click(object sender, EventArgs e) { await Connect(); }`. Then use all the async methods available in the class objects you use. All classes that perform `IO` tasks make use of async methods (sometimes just those are available). E.g., `var data = await reader.ReadLineAsync();`. You can also run `Connect()` in a `Task`, but you cannot access UI elements directly in this case. – Jimi Sep 26 '20 at 16:25
  • ... You actually shouldn't access UI elements from that method. It should not be a concern of `Connect()` whether is `textBox1`, or any other Control, that receives the data. You can use a [IProgress](https://docs.microsoft.com/en-us/dotnet/api/system.progress-1) delegate to update the UI, passing a `Progress` object to the method. In this case, you can also use `Task.Run()` to run the code in `Connect(IProgress updateMethod)`. Then call `updateMethod.Report($"Data: {data}" + Environment.NewLine);`. The delegate updates whatever Control is meant to present the data. – Jimi Sep 26 '20 at 16:38
  • @Jimi _You actually shouldn't access UI elements from that method_ - Wrong warning, i guess - [How do SynchronizationContext and TaskScheduler relate to await?](https://devblogs.microsoft.com/dotnet/configureawait-faq/#how-do-synchronizationcontext-and-taskscheduler-relate-to-await). – aepot Sep 26 '20 at 23:17
  • @aepot Nothing to do with async/await, but with [Separation of Concerns](https://en.wikipedia.org/wiki/Separation_of_concerns) – Jimi Sep 26 '20 at 23:20
  • Contrary to the wording of your title and question, the `ConnectAsync()` method is not blocking your UI thread. It's the other stuff that is. It's not sufficient to just use `ConnectAsync()`. You have to go async all the way, i.e. use asynchronous methods for all socket operations. See duplicates. – Peter Duniho Sep 27 '20 at 02:56

0 Answers0