Search code examples
vb.netasync-awaitconsole-applicationprogram-entry-point

Error: The 'Main' method cannot be marked 'Async'


VB.NET does not support Async Main. This code precompiles but fails a build:

Friend Module SomeConsoleApp
  Friend Async Sub Main
    Await Task.Delay(1000)
  End Sub
End Module

The build error, of course, is:

The 'Main' method cannot be marked 'Async'

I've seen constructs such as this, which at first glance would seem to greatly simplify the situation:

Friend Module SomeConsoleApp
  Friend Sub Main()
    Dim oTask As Task = SomeFunctionAsync()
    oTask.Wait()
  End Sub

  Friend Async Function SomeFunctionAsync() As Task
    Await Task.Delay(1000)
  End Function
End Module

But I believe that to be too simple. It runs, yes, but it'll deadlock if SomeFunctionAsync performs a blocking operation that waits for completion.

What's the safest (and easiest) way to call an Async function in a VB.NET console app?


Solution

  • This can be accomplished safely with Stephen Cleary's Nito.AsyncEx utility:

    Assuming your project is compatible with its version support, install the package and use a construct similar to this:

    Friend Module SomeConsoleApp
      Friend Sub Main()
        AsyncContext.Run(Function() SomeFunctionAsync())
      End Sub
    
      Friend Async Function SomeFunctionAsync() As Task
        Await Task.Delay(1000)
      End Function
    End Module
    

    This happens to be the Run() method's second overload. Here they are in their entirety:

    1. Run(action As Action)
    2. Run(action As Func(Of Task))
    3. Run(Of TResult)(action As Func(Of Task(Of TResult))) As TResult
    4. Run(Of TResult)(action As Func(Of TResult)) As TResult