0

I'm trying to understand how to run callback functions in an async console application. My base console app code looks as follows:

    using Nito.AsyncEx;

    static void Main(string[] args)
    {
        AsyncContext.Run(() => MainAsync());
    }

    static async Task MainAsync()
    {


    }

The method that I want to run in Async mode is the following from a websocket api:

using ExchangeSharp;

public static void Main(string[] args)
{
    // create a web socket connection to Binance. Note you can Dispose the socket anytime to shut it down.
    // the web socket will handle disconnects and attempt to re-connect automatically.
    ExchangeBinanceAPI b = new ExchangeBinanceAPI();
    using (var socket = b.GetTickersWebSocket((tickers) =>
    {
        Console.WriteLine("{0} tickers, first: {1}", tickers.Count, tickers.First());
    }))
    {
        Console.WriteLine("Press ENTER to shutdown.");
        Console.ReadLine();
    }
}

The above code is meant to lock a console app and subscribe to an event which receives data, and to do something with the received data.

What I want to do is run the above in a separate thread or in async so that I can continue with my code in the MainAsync() function.

My C# experience with this is limited. Will appreciate any help!

ceds
  • 2,097
  • 5
  • 32
  • 50
  • From what i can gather, if you put more code before `Console.WriteLine("Press ENTER to shutdown.");` it will already work asynchronously... its paused on the readline, because the application will exit, this is the normal process of a console app.. Do stuff or wait for input, or terminate – TheGeneral May 23 '18 at 06:42

2 Answers2

1

According to source code GetTickersWebSocket isn't a blocking call.

The only blocking call you've posted is Console.ReadLine. ExchangeBinanceAPI has its own callback-based asynchrony, so, just throw away Console.ReadLine, or place more code before it:

static async Task MainAsync()
{
    ExchangeBinanceAPI b = new ExchangeBinanceAPI();
    using (var socket = b.GetTickersWebSocket((tickers) =>
    {
        Console.WriteLine("{0} tickers, first: {1}", tickers.Count, tickers.First());
    }))
    {
        // code continues here

        Console.WriteLine("Press ENTER to shutdown.");
        Console.ReadLine();
    }
}

As a side note.

I'm not familiar with this project, but source code shows poor man's aynchrony inside WebSocketWrapper:

Task.Factory.StartNew(ListenWorkerThread)

// inside ListenWorkerThread
_ws.ConnectAsync(_uri, CancellationToken.None).GetAwaiter().GetResult();
result = _ws.ReceiveAsync(receiveBuffer, _cancellationToken).GetAwaiter().GetResult();

and so on.

There are attempts to call asynchronous code in synchronous way.
Instead of this, at least ListenWorkerThread must be converted to async method, and it definitely must not be called via Task.Factory.StartNew.

I'd post a request to rewrite code in true asynchronous manner, if I have to use this project.

Dennis
  • 37,026
  • 10
  • 82
  • 150
1

Async method would not block the caller thread if you use it directly, you can just call it anywhere before Consolo.ReadLine() then use returned Task to handle the result if you need.

public static void Main(string[] args)
{
    // Would not block the thread.
    Task t = MainAsync();

    // Only if you need. Would not block the thread too.
    t.ContinueWith(()=> { code block that will run after MainAsync() });

    // create a web socket connection to Binance. Note you can Dispose the socket anytime to shut it down.
    // the web socket will handle disconnects and attempt to re-connect automatically.
    ExchangeBinanceAPI b = new ExchangeBinanceAPI();
    using (var socket = b.GetTickersWebSocket((tickers) =>
    {
        Console.WriteLine("{0} tickers, first: {1}", tickers.Count, tickers.First());
    }))
    {
        Console.WriteLine("Press ENTER to shutdown.");
        Console.ReadLine();
    }
}
Alex.Wei
  • 1,798
  • 6
  • 12