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

C# 确定网络客户端连接时如何正确排队工作,c#,multithreading,asynchronous,threadpool,C#,Multithreading,Asynchronous,Threadpool,我一直在阅读关于Threadpool.QueueUserWorkItem(我一直在使用的)、Task.Run和Task.Factory.StartNew的文章,但仍然不清楚这里的正确选项是什么。似乎由于我的工作不受CPU限制,我不应该使用Task.Run 我有自己的线程正在运行,等待连接: Thread listenThread = new Thread(() => ListenForConnection()); listenThread.Name = "lThread"; listenT

我一直在阅读关于
Threadpool.QueueUserWorkItem
(我一直在使用的)、
Task.Run
Task.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元素

ThreadPool.QueueUserWorkItem
是这里的首选方法还是我的选择太远了

编辑:需要注意的是,
HandleClient
功能通常需要5到30毫秒的时间,所以工作不是很繁重

我想这样说:

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

QueueUserWorkItem
StartNew
Run
或多或少是等效的。我会选择Task.Run,因为这是最现代的方式

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

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


catch(Exception){}
这个我不明白。这可能会隐藏bug。此外,如果存在错误,则很可能是永久性错误。这种错误处理将使循环变成一个繁忙的循环,消耗100%的CPU代码。将捕捉器移出循环。

线程和线程池有点旧。现代的是Task.Fastory.StartNew和Task.Run。两者都是具有更好功能的线程池。该应用程序的工作性质意味着在任何给定时间只有一个人可以与之进行物理交互,但可能随时有x(多达15)个客户端连接并等待,因此许多并发连接不太重要。我还在
HandleClient
中做一些UI工作,目前使用的是
Dispatcher.Invoke
,哪种方法可能不是最好的?你当然是对的,我会在那里添加更具体的错误处理,并提醒用户网络问题。是的,15个并不多。UI从异步IO和WAIT中获益匪浅。非常富有成效。我发现让网络层知道用户界面有点脏。但是既然已经是你的方法了,就不要考虑使用任务。您将能够删除所有Dispatcher.Invoke调用,并且仍然有一个响应的UI。另一种方法是不做任何更改,而是使用您拥有的,因为它是可以的。这也是我想知道的。我不确定在我的
HandleClient
函数中在哪里使用
wait
,因为函数中没有太多内容。我有一个
observateCollection activeMachines=newobservateCollection()它保存有关客户端的所有信息。在大多数情况下,我只是添加或更新该列表中的类元素,因此操作非常快。所以也许里面没有什么东西可以等待呢?也许我可以坚持使用
QueueUserWorkItem
通常,每个套接字都有一个读取循环。但回顾这一点,将是另一个问题。听起来你有一个有效的解决方案。