当此代码无法连接到服务器时,此代码不处理抛出的异常。任何想法为什么?谢谢!
public Form1()
{
InitializeComponent();
StartClient();
}
async private Task StartClient()
{
try
{
await ConnectToServerAsync();
}
catch (System.Net.Sockets.SocketException)
{
MesssageBox.Show("TEST");
}
}
private Task ConnectToServerAsync()
{
return Task.Factory.StartNew(() => client.Connect(host, port));
}
答案 0 :(得分:1)
事情是:" async void"是非常危险的构造,几乎不会出现在您的生产代码中。异步方法不是内部语句列表,它是一种从一个语句切换的状态机,等待"对另一个人的陈述,在等待"等待"之间做各种事情。因此,一旦在状态机内部引发异常,就需要特殊的上下文来保留堆栈跟踪等.Void方法不提供这样的上下文。返回任务或任务< something>代替。
作为进一步阅读,我可以推荐Phil Haack非常好的博文:http://haacked.com/archive/2014/11/11/async-void-methods/
答案 1 :(得分:1)
此代码存在各种问题。首先,使用async void
仅适用于事件处理程序。无法等待async void
方法,并且无法处理它抛出的任何异常。其次,Task.Factory.StartNew(()=>client.Connect(host,port))
伪造异步执行。它仍然阻止一个线程。异步执行意味着在等待操作完成时阻止 no 线程。
我假设您使用TcpClient。该类已经有一个ConnectAsync方法,它以异步方式连接。您可以将代码简化为:
private async Task StartClient()
{
try
{
await client.ConnectAsync(host,port);
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString());
}
}
如果你想启动客户端以响应UI事件,例如点击按钮,你会写:
async void Button1_Click(object sender, EventArgs e)
{
await StartClient();
}
或
async void Button1_Click(object sender, EventArgs e)
{
try
{
await StartClient();
//Work with the client
}
catch(Exception exc)
{
MessageBox.Show(exc.ToString());
}
}
最后,使用日志库而不是MessageBox.Show
,例如log4net
,这样您就不会因线程问题而丢失异常消息。