KansaiRobot
KansaiRobot

Reputation: 9912

Asynchronous operations in a console application?

I am programming in C#. My question is: Is there any point (and if there is, any example?) in using asynchronous operations in a console application??

Let me explain. Suppose I am writing a windows application (with buttons, and other widgets..) In this case the main window will be displayed and then the program will wait for events right? (the user pressing a button, the user doing this or that, etc). If the user does nothing, the application just sits there waiting (but not using CPU I think)

On the contrary, when doing a console application, the program starts and perform some operations, perhaps receive some input from the user process things and finalize.

Now, think of synchronous and asynchronous operations. Say I want to do some operation and when this operation finishes, do something else. That makes sense in a windows application. For example the user presses a button and the program starts an operation asynchronously but does not wait for it to be completed. The button operation finishes.

Later on when the operation finishes, it calls some other function and do what it has to do. In between there is no wait or block.

But what if I do the same in a console application? If I call an asynchronous operation, I have to block it with a ManualResetEvent somewhere in order for the main function not to finish right? But then if I block it, there is no point in the asynchronicity of the operation, is there??

Are asynchronous operations even used in console applications??

Upvotes: -1

Views: 1094

Answers (2)

Matthew Watson
Matthew Watson

Reputation: 109567

As an example of a console application that can benefit from async/await, consider a requirement where you need to obtain some data from a remote web site.

You want to get the data as quickly as possible, and the data is available from multiple web sites. Therefore, you can implement this by asynchronously attempting to obtain the data from multiple web sites simultaneously, but just use the most quickly returned data (and ignore the other data).

An example of this could be obtaining the current time from an internet server.

Here's a complete compilable console app which does this:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine(GetTime().Result);
        }

        public static async Task<DateTime> GetTime()
        {
            return await Task.WhenAny
            (
                Task.Run(() => GetNetworkTime("time.windows.com")),
                Task.Run(() => GetNetworkTime("1.uk.pool.ntp.org")),
                Task.Run(() => GetNetworkTime("time.nist.gov"))
            ).Result;
        }

        public static async Task<DateTime> GetNetworkTime(string ntpServer)
        {
            IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList;

            if (address == null || address.Length == 0)
                throw new ArgumentException("Could not resolve ip address from '" + ntpServer + "'.", nameof(ntpServer));

            IPEndPoint ep = new IPEndPoint(address[0], 123);
            var result = await GetNetworkTime(ep);

            return result;
        }

        public static async Task<DateTime> GetNetworkTime(IPEndPoint ep)
        {
            using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
            {
                await Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, ep, null);

                byte[] ntpData = new byte[48]; // RFC 2030 
                ntpData[0] = 0x1B;

                await Task.Factory.FromAsync(
                    socket.BeginSend(ntpData, 0, ntpData.Length, SocketFlags.None, null, null),
                    socket.EndSend);

                await Task.Factory.FromAsync(
                    socket.BeginReceive(ntpData, 0, ntpData.Length, SocketFlags.None, null, null),
                    socket.EndReceive);

                return asDateTime(ntpData);
            }
        }

        static DateTime asDateTime(byte[] ntpData)
        {
            byte offsetTransmitTime = 40;
            ulong intpart = 0;
            ulong fractpart = 0;

            for (int i = 0; i <= 3; i++)
                intpart = 256*intpart + ntpData[offsetTransmitTime + i];

            for (int i = 4; i <= 7; i++)
                fractpart = 256*fractpart + ntpData[offsetTransmitTime + i];

            ulong milliseconds = (intpart*1000 + (fractpart*1000)/0x100000000L);

            TimeSpan timeSpan = TimeSpan.FromTicks((long) milliseconds*TimeSpan.TicksPerMillisecond);

            DateTime dateTime = new DateTime(1900, 1, 1);
            dateTime += timeSpan;

            TimeSpan offsetAmount = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
            DateTime networkDateTime = (dateTime + offsetAmount);

            return networkDateTime;
        }
    }
}

Upvotes: 2

Radinator
Radinator

Reputation: 1088

In this case the main window will be displayed and then the program will wait for events right?

But this has nothing to do with asynchronus progamming. This is a simple observer pattern. A function/void in your class is "listening" for a event is raised. The component (Button, Checkbox) raises the event (Button.Click, Checkbox.CheckedChanged).

synchronous and asynchronous operations

For example the user presses a button and the program starts an operation asynchronously but does not wait for it to be completed. The button operation finishes.

You have to differn: synchronous operation are all the things that follow this function/sub signature:

<accessability> <return-type> <name>(<parameter>) {}

like:

public void DoSomething(int parameter1, string parameter2)
{
    Console.WriteLine(parameter1);
    Console.WriteLine(parameter2);
}

Asynchronous operation follow this:

<accessability> async <return-type> <name>(<parameter>) {}

where <return type> is either void (for asynchronus event handler) or Task (for asynchronous subroutines that would return void) OR Task<T> (for functions that would normally return T)

So calling these async marked methods is done by "awaiting" them:

private async void myObject_HandleEvent(object sender, EventArgs e)
{
    string text = await GetStringFromDataBaseAsync();
}

private Task<string> GetStringFromDataBaseAsync()
{
    string result = "";
    // Obtain value and store it in value
    return result;
}

If you consider using asynchronous programming, then look for pieces of your code that take long time to run (querying databases, I/O transactions, ...). This - normally - can be made asynchronously and run much faster. (But take care you don't create race conditions).

Last but not least:

Are asynchronous operations even used in console applications??

It depends.

E.g: If you want to load data (from database/local file system/...) then you can use async/await to speed up your app. Since Console application are not using any kind of UI, you can't use it to improve your UI.

Upvotes: 1

Related Questions