我的理解是,异步等待用于IO(网络、数据库等),并行任务用于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连接并尽快释放它,以便扩展到大量连接。
我觉得我在这里混合范例。
谢谢
最佳答案
我的理解是,异步等待用于IO(网络、数据库等),并行任务用于CPU。
我会说理解是错误的。async
/await
用于任何异步操作,无论是I/O还是CPU绑定。
…我关心的问题是如何使用任务。运行以开始工作我是否仍在创建一个块?
“一个街区”?你认为你会创造出什么样的街区?
就我个人而言,我不会那样写代码。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();
}
笔记:
dummy
_
变量只是为了防止编译器警告您忽略了未等待的异步返回)由于忽略返回的
Task
对象,因此不会收到抛出的异常。因此,您应该将适当的异常处理添加到ProcessMessage()
方法本身。我同意评论SHR关于清理的观点。您没有提供完整的代码示例,因此我们不知道诸如
StoreMessage()
方法的作用。但是,假设/希望您在其中的某个地方有正确而优雅地关闭连接并关闭套接字的逻辑。关于c# - C#4.5 - TCP服务器(主要是数据库插入)是否应该在Task上启动每个客户端,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29270612/