从等待的异步函数中捕获异常

时间:2015-11-10 14:53:09

标签: c# async-await httpclient

我得到了以下内容:

public async Task<bool> IsAuthenticatedAsync()
    {
        using (HttpClient client = new HttpClient())
        {
            using (MultipartFormDataContent content = new MultipartFormDataContent())
            {
                content.Add(new StringContent(this.Username, Encoding.UTF8), "username");
                content.Add(new StringContent(this.Password, Encoding.UTF8), "password");
                try
                {
                    HttpResponseMessage message = await client.PostAsync(authenticatedUrl, content);
                    if (message.StatusCode == HttpStatusCode.Accepted)
                        return true;
                    return false;
                }
                catch(HttpRequestException)
                {
                    System.Windows.Forms.MessageBox.Show("Some text.");
                }
            }
        }
        return false;
    }

其中authenticatedUrl是静态Uri

现在假设网络服务器不可用(或地址错误)await client.PostAsync(authenticatedUrl, content)会引发HttpRequestException,因此try-catch

问题是异常没有被抓住。我尝试关闭Just My Code,但只是添加了其他例外情况(例如SocketException),建议使用here,但仍然不允许catch处理异常。

为什么没有抓住异常?

修改

主要表单(GUI):

public GUI(...)
{
    ...
    CheckLoginState(username, password);
    ...
}

private async void CheckLoginState(string username, string password)
{
    User user = new User(username, password);
    if (user.Username != null && user.Password != null && await user.IsAuthenticatedAsync())
        abmeldenToolStripMenuItem.Enabled = true;
}

1 个答案:

答案 0 :(得分:0)

我很确定异常没有被捕获,因为它包含在从“CheckLoginState”方法调用返回的任务中,并且因为你没有等待那个任务,所以你的异常永远不会被抛出。从它的外观来看,你是从构造函数调用它,所以我假设你不能将“公共GUI”变成“公共异步虚拟GUI”。

为了测试,您可以尝试阻止等待ex:

public GUI(...)
{
    ...
    var task = CheckLoginState(username, password).Wait();
    if(task.IsFaulted && task.Exception != null)
    {
        throw task.Exception
    }
    ...
}

另一种方法是让async / await-pattern自然传播并将其绑定到一个事件(不知道你是使用wpf还是winforms,所以我假设是wpf)。

public GUI(...)
{
    this.Loaded += async (obj, eventArgs) => await CheckLoginState(username, password);
    ...
}

当然,它不一定是“加载”事件。重点是,事件可以是异步的,构造函数不能(根据我所知道的)。