【问题标题】:Program ends before async result is received程序在收到异步结果之前结束
【发布时间】:2021-04-12 17:28:36
【问题描述】:

我正在编写一个程序来通过命令行与 Spotify API 进行交互。

我这里有一些代码来获取命令,然后执行相关函数从 Spotify 中检索数据。

这段代码说明了问题,我省略了不相关的代码。

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());
        }
    }
}

HandleCommands() 中的两个 if 语句调用 PlayerController 并等待方法的结果。出于某种原因,如果我使用 await PlayerController.MethodCall() 进行调用,但是在程序完成执行之前结果不会返回。

奇怪的是,如果我使用PlayerController.MethodCall().Result,这不是问题。

任何帮助将不胜感激,因为我真的不想使用.Result。谢谢!

【问题讨论】:

  • 除非 HandleCommands 是一个事件处理程序(看起来不像),否则签名应该是 async Task,而不是 async void
  • 好的,谢谢。我一定会改变它。你认为这会对上面讨论的问题产生影响吗?或者这只是代码设计的改进?
  • 极有可能。使用 async void 无法正确捕获任何抛出的异常,您无法正确等待其完成。
  • console.ReadLine() 异步方法之外
  • HttpClient is intended to be instantiated once per application, rather than per-use.。也尊重IDisposable HttpResponseMessageusing(var response = await httpClient.GetAsync(...)) { ... }

标签: c# .net-core async-await spotify


【解决方案1】:

HandleCommands 的签名是个问题

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

您没有展示如何调用此方法,但我认为它类似于以下内容:

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

因为async void 方法没有返回Task 并且调用者不能“观察”它的完成。
因此应用程序无需等待任务完成即可完成。

修复 - 将方法签名更改为以下并等待任务完成

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

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

【讨论】:

  • 这个问题已经解决了,谢谢!我不知道这两个签名之间的差异会产生如此大的影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-03
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多