我正在通过使用async / await模式来解决(看起来如此)非常着名的异常处理问题。具体来说,我的上下文是在HTTP客户端上,但我也尝试过一个更简单的测试,它的行为相同。
考虑以下程序,这是我原始应用程序上下文的超简化版本。
class Program
{
static void Main(string[] args)
{
Test();
Console.Write("Press any key...");
Console.ReadKey();
Console.WriteLine();
}
static async void Test()
{
var c = new MyClient();
try
{
var uri = new Uri("http://www.google.com/"); //valid address
var s = await c.GetString(uri);
Console.WriteLine(s.Length);
}
catch (WebException ex)
{
Console.WriteLine(ex.Message);
}
try
{
var uri = new Uri("http://www.foo.bah/"); //non-existent address
var s = await c.GetString(uri);
Console.WriteLine(s.Length);
}
catch (WebException ex)
{
Console.WriteLine(ex.Message);
}
}
}
class MyClient
{
public async Task<string> GetString(Uri uri)
{
var client = new HttpClient();
return await client.GetStringAsync(uri);
}
}
当程序启动时,它会将第一个网站的页面作为字符串下载,然后显示其长度:没关系。之后,当对无效地址执行相同的操作时,客户端会引发WebException(这就是我想要的),但它没有被捕获。
更新:因为“未被捕获”,我的意思是代码实际上不会流经“catch”分支并以静默方式显示异常消息。相反,VS IDE会显示异常,并且调试会中断。
任何可以解决异常的合适解决方案?
非常感谢提前。
答案 0 :(得分:1)
虽然你已经发现异常是HttpRequestException
而不是WebException
,但我仍然想强调一些关于async-await运算符使用的重要事项。
async void
类型为fire&amp;忘了,只是&amp;仅适用于事件处理程序。调试代码: -
由于您在Test方法中使用async void,因此控件返回到调用者并继续执行行Console.Write("Press any key...");
,而没有任何有关Task的信息,然后您正在等待用户输入。
同时等待来自等待方法的响应,并在Test方法内继续执行。
如果您在main()内注释掉行Console.ReadKey();
或者用户立即提供输入,那么您会注意到响应可能会打印也可能不打印。这是因为您不是在等待任务执行时,您只需信任用户,在任务完成之前他不会输入任何内容。
解决方案: -
解决方案是从Test()返回Task然后等到它完成,下面是更新的代码也注意在方法名称的末尾添加Async是你必须遵循的命名约定,以免你摆脱区分异步和同步方法。
class Program
{
static void Main(string[] args)
{
Task task = TestAsync();
Console.Write("Press any key...");
task.wait();
//Console.ReadKey();
Console.WriteLine();
}
static async Task<string> TestAsync()
{
var c = new MyClient();
try
{
var uri = new Uri("http://www.google.com/"); //valid address
var s = await c.GetStringAsync(uri);
Console.WriteLine(s.Length);
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.Message);
}
try
{
var uri = new Uri("http://www.foo.bah/"); //non-existent address
var s = await c.GetStringAsync(uri);
Console.WriteLine(s.Length);
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.Message);
}
//to avoid compiler error
return null;
}
}
class MyClient
{
public async Task<string> GetStringAsync(Uri uri)
{
var client = new HttpClient();
return await client.GetStringAsync(uri);
}
}