gpt4 book ai didi

c# 4.5 - 一个主要做数据库插入的 TCP 服务器是否应该在一个任务上启动每个客户端

转载 作者:可可西里 更新时间:2023-11-01 02:51:46 28 4
gpt4 key购买 nike

我的理解是,async await 是针对 IO(网络、数据库等)的,而 parallel task 是针对 cpu 的。

注意:为了使本文简洁,这段代码有点苛刻。

我有一个用 c# 创建的 Windows 服务,它具有以下代码

while (true)
{
var socket = await tcpListener.AcceptSocketAsync();
if (socket == null) { break; }

var client = new RemoteClient(socket);
Task.Run(() => client.ProcessMessage());
}

在 RemoteClient 类中,ProcessMessage 方法执行此操作

byte[] buffer = new byte[4096];
rawMessage = string.Empty;
while (true)
{
Array.Clear(buffer, 0, buffer.Length);
int bytesRead = await networkStream.ReadAsync(buffer, 0, buffer.Length);
rawMessage += (System.Text.Encoding.ASCII.GetString(buffer).Replace("\0", string.Empty));

if (bytesRead == 0 || buffer[buffer.Length - 1] == 0)
{
StoreMessage();
return;
}
}

所以我让 I/O 工作异步进行。但我的顾虑和问题是使用 Task.Run 开始工作我是否仍在创建 block ?

我正在尝试建立一个 TCP 连接并尽快释放它,以便扩展到大量连接。

我觉得我在这里混合了范式。

谢谢

最佳答案

My understanding is that async await is for IO (network, db, etc) and parallel task is for cpu.

我会说理解是不正确的。 async/await 适用于任何异步操作,无论是 I/O 还是 CPU 绑定(bind)。

…my concern and my question is in using Task.Run to kick off the work am I still creating a block?

“一 block ”?您认为否则会创建什么样的 block ?


就个人而言,我不会那样写代码。 accept 操作已经在线程池线程中完成(或在同一线程中同步完成),即来自 IOCP 线程池的线程。最好为该线程上的连接设置一些初始条件,然后从那里启动 I/O。没有理由在另一个线程上排队工作。

所以我写代码的方式是这样的:

async Task ProcessMessage()
{
byte[] buffer = new byte[4096];
rawMessage = string.Empty;
while (true)
{
Array.Clear(buffer, 0, buffer.Length);
int bytesRead = await networkStream.ReadAsync(buffer, 0, buffer.Length);
rawMessage += (System.Text.Encoding.ASCII.GetString(buffer).Replace("\0", string.Empty));

if (bytesRead == 0 || buffer[buffer.Length - 1] == 0)
{
StoreMessage();
return;
}
}
}

然后在你的服务中:

while (true)
{
var socket = await tcpListener.AcceptSocketAsync();
if (socket == null) { break; }

var client = new RemoteClient(socket);
var _ = client.ProcessMessage();
}

注意事项:

  • 虚拟 _ 变量只是为了防止编译器警告您有关被忽略的、未等待的异步返回)
  • 由于您忽略了返回的 Task 对象,因此您不会收到抛出的异常。因此,您应该为 ProcessMessage() 方法本身添加适当的异常处理。
  • 我同意评论者 shr 关于清理的观点。您没有提供完整的代码示例,所以我们不知道例如StoreMessage() 方法可以。但大概/希望你在某个地方有逻辑可以正确和优雅地关闭连接并关闭套接字。

关于c# 4.5 - 一个主要做数据库插入的 TCP 服务器是否应该在一个任务上启动每个客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29270612/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com