我正在尝试学习那些“新”关键字,并试图实现一个简单的异步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是一个长时间运行的进程,还是对线程池无关紧要?
希望我的问题现在更清楚了,谢谢你们:)
答案 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是一个长时间运行的进程,还是对线程池无关紧要?
没关系。