0

快速背景。在我构建的类库中使用了 Flurl,以简化与云存储 api 通信的代码。从用于测试所有方法的控制台应用程序调用库时效果很好。当尝试通过简单的 winform 使用完全相同的类库时,使用控制台应用程序快速返回的相同方法现在似乎永远不会返回结果。调试时,下面的代码会到达“.GetAsync()”行,然后永远不会返回结果,还会阻止调试会话继续。不会抛出任何错误消息。

我在 Flurl 网站上发现有人似乎遇到了同样的问题,但是他们似乎没有按照建议在此处发布问题。任何可以为我指明正确方向的事情都将不胜感激。

包裹在异步方法中的 Flurl 代码

public async Task<AccountInfo> Authorize()
    {
        string credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(Utils.ToNonSecureString(accountId) + ":" + Utils.ToNonSecureString(applicationKey)));
        var result = await B2UrlType.Authorize
            .WithHeader("Authorization", "Basic " + credentials)
            .GetAsync()
            .ReceiveJson<AccountInfo>();
        return result;
    }

完美运行的控制台应用调用代码

if (client == null)
        {
            var vault = new Vault();
            Console.WriteLine("Retrieving account keys");
            client = new Client(vault.GetAccountId(), vault.GetApiKey());
            Console.WriteLine("Successfully retrieved account keys");
            Console.WriteLine("Created new client");
            client.Authorize().GetAwaiter().GetResult();
        }

Winform调用代码不返回

private Client client;
    public MainWindow()
    {
        InitializeComponent();
        var vault = new Vault();
        client = new Client(vault.GetAccountId(), vault.GetApiKey());
        client.Authorize().GetAwaiter().GetResult();

    }
4

2 回答 2

1

您的原始代码挂起,因为您调用GetResult(). 这不是 Flurl 特有的问题;这是async 101

您的修复工作有效,因为您不再阻塞,但您也没有await调用Auth(),这实际上等同于仅在client.Authorize()没有构造函数的情况下调用awaitGetResult()直接从MainWindow()构造函数调用。您不再阻塞,而是一劳永逸,这意味着可能发生的任何异常都client.Authorize不会被观察到,从而导致难以追踪的错误。

经验法则:与任何异步库一样,从其他异步方法调用 Flurl 的异步方法并尽可能等待它们。在控制台应用程序中,您必须在某处阻塞主线程,否则应用程序将在任务完成之前简单地退出。(我喜欢在最顶层做 - 定义一个包含MainAsync所有工作的方法并MainAsync().Wait()Main.处理程序

我很久没有做过 WinForms,但根据其他答案,初始化代码似乎是一个不错的事件Window.Load。移动您的授权呼叫将是一个很好的解决方案。像这样的东西:

private async void MainWindow_Load(object sender, System.EventArgs e)
{
    await client.Authorize();
}
于 2016-12-24T15:12:04.643 回答
0

这是有效的,但我仍然不确定为什么......

    private Client client;
    public MainWindow()
    {
        InitializeComponent();
        var vault = new Vault();
        client = new Client(vault.GetAccountId(), vault.GetApiKey());
        Auth();

    }

    private async void Auth()
    {
        await client.Authorize();
    }

将授权调用包装在异步方法中允许 httpPost 完成并返回结果。

于 2016-12-24T00:07:05.910 回答