正确使用async / await和Task

时间:2014-08-05 14:57:56

标签: c# visual-studio-2012 asynchronous task

我正在尝试学习那些“新”关键字,并试图实现一个简单的异步udp服务器。

public class UdpServerSync
{
    private CancellationTokenSource _cts;
    private CancellationToken _token;
    private UdpClient _client;

    public void Start()
    {
        Console.WriteLine("Start server");
        _cts = new CancellationTokenSource();
        _token = _cts.Token;
        var ipAddress = IPAddress.Parse("192.168.0.25");
        var ip = new IPEndPoint(ipAddress, 7070);
        try
        {
            Task.Run(async () =>
            {
                using (_client = new UdpClient(ip))
                {                        
                    while (!_token.IsCancellationRequested)
                    {
                        var receivedData = await _client.ReceiveAsync();
                        var msg = Encoding.ASCII.GetString(receivedData.Buffer);
                        // Process request e.g ProcessRequest(msg);
                        Console.WriteLine(msg);
                    }
                }
            }, _token).ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }    
    }

    public void Stop()
    {
        Console.WriteLine("Stop server");
        if (_cts != null) _cts.Cancel();
    }

然后像这样使用它(用于测试目的):

var server = new UdpServerSync();
server.Start();
await Task.Delay(5000);
server.Stop();

上面的代码只是一个概念证明,它不是代码审查。通过一个简单的udp服务器,我的意思是一个带有udpclient的while循环,用于监听udp消息并将它们写入控制台 - 无需处理或处理错误。

Task.Delay的原因只是因为它是调用服务器的start()和stop()方法的概念证明。

缩小我的问题范围:

1)如果我打算从WPF应用程序的开始按钮调用Start()和Stop()方法,我应该使用server.Start()还是Task.Run?我不想等待电话,因为无法知道用户希望服务器启动多长时间。

2)在服务器代码“ProcessRequest(msg)中,如果那是另一个库中的void方法,我应该使用Task.Run()来执行它以避免服务器线程被阻塞或有更好的方法吗?

3)当我们执行async / await时,await语句中的代码是否在线程池的新线程中执行?

4)我可以指定UdpServer是一个长时间运行的进程,还是对线程池无关紧要?

希望我的问题现在更清楚了,谢谢你们:)

1 个答案:

答案 0 :(得分:0)

  

1)如果我打算从WPF应用程序的开始按钮调用Start()和Stop()方法,我应该使用server.Start()还是Task.Run?

使用您现在拥有的代码,您只需拨打Start(即Task.Run)。 IMO,对Task.Run的调用是不必要的。而对ConfigureAwait的调用肯定是,因为没有await可供配置。

  

我不想等待通话,因为无法知道用户希望服务器启动多长时间。

但你可能想知道任何异常。所以,考虑如何处理这些。一种解决方案是将返回的Task保存为属性。或者,您可以await它(记住,它运行多长时间并不重要,因为它是异步等待)。

  

2)在服务器代码“ProcessRequest(msg)中,如果那是另一个库中的void方法,我应该使用Task.Run()来执行它以避免服务器线程被阻塞或有更好的方法吗?

没有“服务器线程”。但是如果ProcessRequest需要很长时间,那么您可能需要考虑使用Task.Run,以便您的代码在处理该代码时接受下一个请求。

  

3)当我们执行async / await时,await语句中的代码是否在线程池的新线程中执行?

没有。我的博客上有async intro更详细的内容。

  

4)我可以指定UdpServer是一个长时间运行的进程,还是对线程池无关紧要?

没关系。