Search code examples
c#.net-coreasync-awaitspotify

Program ends before async result is received


I am writing a program to interact with the Spotify API via a command line.

I have some code here to take a command, and then execute the relevant function to retrieve data from Spotify.

This code shows the problem, I have left out irrelevant code.

public class CommandHandler
{
    public async void HandleCommands()
    {
        var spotifyCommand = GetCommand();

        if (spotifyCommand == SpotifyCommand.Current)
        {
            WriteCurrentSong(await new PlayerController().GetCurrentlyPlayingAsync());
        }

        if (spotifyCommand == SpotifyCommand.NextTrack)
        {
            WriteCurrentSong(await new PlayerController().NextTrackAsync());
        }

        Console.ReadLine();
        //end of program
    }
}

public class PlayerController
{
    public async Task<SpotifyCurrentlyPlaying> NextTrackAsync()
    {
        using (var httpClient = new HttpClient())
        {
            //removed code to set headers etc

            //Skip Track
            var response = await httpClient.PostAsync("https://api.spotify.com/v1/me/player/next", null);

            if (response.StatusCode != HttpStatusCode.NoContent)
            {
                //code to handle this case, not important
            }
            
            return await GetCurrentlyPlayingAsync();
        }
    }

    public async Task<SpotifyCurrentlyPlaying> GetCurrentlyPlayingAsync()
    {
        using (var httpClient = new HttpClient())
        {
            //removed code to set headers etc
            
            var response = await httpClient.GetAsync("https://api.spotify.com/v1/me/player/currently-playing");

            response.EnsureSuccessStatusCode();

            return JsonSerializer.Deserialize<SpotifyCurrentlyPlaying>(await response.Content.ReadAsStringAsync());
        }
    }
}

The two if statements in HandleCommands() call into PlayerController and await the result of the method. For some reason if I use await PlayerController.MethodCall() the call is made, however, the result does not return before the program finishes executing.

Strangely, this is not an issue if I use PlayerController.MethodCall().Result.

Any help will be greatly appreciated, as I would really rather not use .Result. Thanks!


Solution

  • Signature of the HandleCommands is an issue

    public async void HandleCommands()
    { 
      // ...
    }
    

    You are not showing how this method is called, but I assume it is something like below:

    var handler = new CommandHandler();
    handler.HandleCommands();
    

    Because of async void method doesn't return Task and caller can not "observe" it's completion.
    So application finishes without waiting for task to complete.

    To fix - change method signature to below and await for task to complete

    public async Task HandleCommands()
    { 
      // ...
    }
    
    var handler = new CommandHandler();
    await handler.HandleCommands();