确定在网络客户端连接时如何正确排队工作

时间:2016-06-30 14:16:35

标签: c# multithreading asynchronous threadpool

我一直在阅读有关Threadpool.QueueUserWorkItem(我一直在使用的内容),Task.RunTask.Factory.StartNew的内容,但我仍然不清楚这里的选项是什么。看来,由于我的工作不受CPU约束,我可能不应该使用Task.Run

我有自己的线程正在运行,等待连接:

Thread listenThread = new Thread(() => ListenForConnection());
listenThread.Name = "lThread";
listenThread.IsBackground = true;
listenThread.Start();

并在其中我只是在做:

tlist = new TcpListener(IPAddress.Parse(ip.ToString()), 27275);
tlist.Start();

while (isRunning) {
     try {
          var client = await tlist.AcceptTcpClientAsync();
          ThreadPool.QueueUserWorkItem(HandleClient, client);
     }
     catch (Exception) { }
}

HandleClient解析客户端发送的消息,如果客户端已经存在,则创建简单类的实例或更新现有实例,存储对连接的引用,并更新一些UI元素。 / p>

ThreadPool.QueueUserWorkItem是首选方法还是我离开?

编辑:只需注意,HandleClient函数通常需要5到30毫秒,所以工作量不是很大

2 个答案:

答案 0 :(得分:1)

QueueUserWorkItemStartNewRun或多或少相同。我选择Task.Run,因为这是最现代化的方式。

你做的方式完全没问题。您选择了一个同步HandleClient实现,它强制您在单独的线程上处理连接。请注意,在许多并发连接的情况下,这会消耗许多资源。如果您对该场景不感兴趣,这不是问题。否则,这是一个破坏者。

如果您使HandleClient真正异步且无阻塞,则无需将该调用推送到线程池。我的建议是仍然这样做,因为它有很小的缺点,它可以保护你免受该方法过长的同步初始部分的影响。

catch (Exception) { }这个我不明白。这可能会隐藏错误。此外,如果出现错误,则很可能是永久性错误。这种错误处理会将循环转换为占用100%的一个CPU代码的繁忙循环。将捕获物移动到循环外部。

答案 1 :(得分:0)

我会这样说:

var tcpListener = new TcpListener(IPAddress.Any, 80);
tcpListener.Start();
while (true)
{
  var tcpClient = tcpListener.AcceptTcpClient();
  Task.Factory.StartNew(() =>
  {
    // Do whatever you like with your TcpClient
  });
}