从winforms应用程序调用Flurl永远不会返回结果

时间:2016-12-23 23:39:16

标签: c# winforms flurl

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

我在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();

    }

2 个答案:

答案 0 :(得分:1)

您的原始代码会挂起,因为您在调用GetResult()时阻止了UI线程。这不是Flurl特有的问题;这是async 101

您的修复有效,因为您不再屏蔽,但您也没有await拨打Auth(),这实际上相当于只调用client.Authorize() {直接来自await构造函数的{1}}或GetResult()。你不再阻止,但是你忘了,这意味着MainWindow()中可能发生的任何异常都将被忽略,导致很难找到的错误。

经验法则:与任何异步库一样,从其他异步方法调用Flurl的异步方法,并尽可能等待它们。在控制台应用程序中,您来阻止主线程,或者应用程序将在任务完成之前退出。 (我喜欢在最顶层执行此操作 - 定义包含所有工作的client.Authorize方法并从MainAsync调用MainAsync().Wait()。)但是使用WinForms应用程序时,可以放置异步的好地方代码,您永远不会阻止或发送忘记:事件处理程序

我很长一段时间没有完成WinForms,但基于其他答案,初始化代码似乎是一个不错的事件Main。移动您的授权电话将是一个很好的解决方案。像这样:

Window.Load

答案 1 :(得分: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完成并返回结果。