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

本文关键字:函数 捕获异常 异步 等待 | 更新日期: 2023-09-27 18:21:18

我得到了以下内容:

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

其中CCD_ 1是一些静态的CCD_。

现在假设Web服务器不可用(或者地址错误),await client.PostAsync(authenticatedUrl, content)抛出一个HttpRequestException,因此抛出try-catch

问题是没有捕捉到异常。我尝试关闭Just My Code,但这只是添加了此处建议的其他异常(即SocketException),仍然不让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;
}

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

我很确定这个异常没有被捕获,因为它被封装在从对"CheckLoginState"-方法的调用返回的任务中,并且由于您没有等待该任务,那么您的异常永远不会被抛出。从外观上看,您是从构造函数调用它的,所以我假设您不能将"公共GUI"变成"公共异步无效GUI"。

为了测试,您可以尝试阻塞等待,例如:

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

另一种方法是让async/await模式自然传播,并将其与事件联系起来(不知道您使用的是wpf还是winforms,所以我假设是wpf)。

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

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