ThreadPool 行为和 TCPListener
ThreadPool behavior and TCPListener
我这样开始 TCPListener
,当工作完成后我关闭 Socket
。
我想知道我开始的 Thread
是不是这样
ThreadPool.QueueUserWorkItem(ConnectClientsThredProc, args);
会自我毁灭,所以我不需要任何外部控制。
有没有人很乐意解释一下我是否担心。
谢谢!
class TCPListenerManager
{
TcpListener tcpListener;
HostListenerItem hostListener;
private bool _isServerWorking = false;
public TCPListenerManager(HostListenerItem hostListenerItem)
{
hostListener = hostListenerItem;
tcpListener = new TcpListener(IPAddress.Parse(hostListenerItem.IP4), hostListenerItem.Port);
var t = Task.Factory.StartNew(async () =>
{
await StartAsync(hostListenerItem.ClientsMax);
});
}
public async Task StartAsync(int clientsMax)
{
tcpListener.Start();
_isServerWorking = true;
for (int i = 0; i < clientsMax; i++)
{
if (_isServerWorking)
{
ServerConnectedEventArgs args = new ServerConnectedEventArgs();
args.TcpClient = await tcpListener.AcceptTcpClientAsync();
args.HostListener = hostListener;
OnServerConnected(args);
ThreadPool.QueueUserWorkItem(ConnectClientsThredProc, args);
}
}
}
private void ConnectClientsThredProc(object obj)
{
var args = (ServerConnectedEventArgs)obj;
if (args.TcpClient.Connected)
{
// Do some job and disconnect
args.TcpClient.Client.Close();
args.TcpClient.Client = null;
}
}
}
当ConnectClientsThredProc
退出时,线程不是"gone"而是返回到池中(这就是线程池首先存在的原因)。无论如何,你确实不应该关心这个,除非你在 ConnectClientsThredProc
中执行了 long-运行 任务。如果它很长 运行 - 最好不要使用线程池线程,而是启动一个新线程(例如通过 Task.Factory.StartNew
+ TaskCreationOptions.LongRunning
)。
此外,您使用 Task.Factory
、async\await、ThreadPool.QueueUserWorkItem
,所有这些都在一小段代码中混合在一起。也许您需要更好地了解这些工具是什么以及它们之间的异同(尤其是 async\await)。比如这是什么原因:
var t = Task.Factory.StartNew(async () =>
{
await StartAsync(hostListenerItem.ClientsMax);
});
您启动一个 task\thread,在其中启动另一个任务,然后等待它退出 - 毫无意义。
您可以使用 Task.Run
而不是 ThreadPool.QueueUserWorkItem
,效果相同。
我这样开始 TCPListener
,当工作完成后我关闭 Socket
。
我想知道我开始的 Thread
是不是这样
ThreadPool.QueueUserWorkItem(ConnectClientsThredProc, args);
会自我毁灭,所以我不需要任何外部控制。
有没有人很乐意解释一下我是否担心。 谢谢!
class TCPListenerManager
{
TcpListener tcpListener;
HostListenerItem hostListener;
private bool _isServerWorking = false;
public TCPListenerManager(HostListenerItem hostListenerItem)
{
hostListener = hostListenerItem;
tcpListener = new TcpListener(IPAddress.Parse(hostListenerItem.IP4), hostListenerItem.Port);
var t = Task.Factory.StartNew(async () =>
{
await StartAsync(hostListenerItem.ClientsMax);
});
}
public async Task StartAsync(int clientsMax)
{
tcpListener.Start();
_isServerWorking = true;
for (int i = 0; i < clientsMax; i++)
{
if (_isServerWorking)
{
ServerConnectedEventArgs args = new ServerConnectedEventArgs();
args.TcpClient = await tcpListener.AcceptTcpClientAsync();
args.HostListener = hostListener;
OnServerConnected(args);
ThreadPool.QueueUserWorkItem(ConnectClientsThredProc, args);
}
}
}
private void ConnectClientsThredProc(object obj)
{
var args = (ServerConnectedEventArgs)obj;
if (args.TcpClient.Connected)
{
// Do some job and disconnect
args.TcpClient.Client.Close();
args.TcpClient.Client = null;
}
}
}
当ConnectClientsThredProc
退出时,线程不是"gone"而是返回到池中(这就是线程池首先存在的原因)。无论如何,你确实不应该关心这个,除非你在 ConnectClientsThredProc
中执行了 long-运行 任务。如果它很长 运行 - 最好不要使用线程池线程,而是启动一个新线程(例如通过 Task.Factory.StartNew
+ TaskCreationOptions.LongRunning
)。
此外,您使用 Task.Factory
、async\await、ThreadPool.QueueUserWorkItem
,所有这些都在一小段代码中混合在一起。也许您需要更好地了解这些工具是什么以及它们之间的异同(尤其是 async\await)。比如这是什么原因:
var t = Task.Factory.StartNew(async () =>
{
await StartAsync(hostListenerItem.ClientsMax);
});
您启动一个 task\thread,在其中启动另一个任务,然后等待它退出 - 毫无意义。
您可以使用 Task.Run
而不是 ThreadPool.QueueUserWorkItem
,效果相同。