C#async - 未处理异常

时间:2017-07-04 09:55:08

标签: c#

当此代码无法连接到服务器时,此代码不处理抛出的异常。任何想法为什么?谢谢!

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

2 个答案:

答案 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,这样您就不会因线程问题而丢失异常消息。