gpt4 book ai didi

c# - 理解使用无限循环时的即发即忘

转载 作者:行者123 更新时间:2023-12-05 06:40:38 25 4
gpt4 key购买 nike

谁能告诉我这样做的最佳实践/正确方法是什么?
我也在使用 WPF,而不是控制台或 ASP.NET。

使用 Listener 接受客户端并为每个客户端派生出一个新的“线程”来处理该客户端的所有 I/O 和异常捕获。

方法 1:触发后忘记,只需将其放入变量即可消除警告。

public static async Task Start(CancellationToken token)
{
m_server = TcpListener.Create(33777);
m_server.Start();
running = true;
clientCount = 0;

// TODO: Add try... catch
while (!token.IsCancellationRequested)
{
var client = await m_server.AcceptTcpClientAsync().ConfigureAwait(false);

Client c = new Client(client);

var _ = HandleClientAsync(c);
}
}

这是客户端处理程序代码:

public static async Task HandleClientAsync(Client c)
{
// TODO: add try...catch
while (c.connected)
{
string data = await c.reader.ReadLineAsync();

// Now we will parse the data and update variables accordingly
// Just Regex and some parsing that updates variables
ParseAndUpdate(data);
}
}

方法 2:同样的事情......但使用 Task.Run()

var _ = Task.Run(() => HandleClientAsync());

方法三:一个中间的非异步函数(怀疑这个好不好。应该一直是Async)
但这至少摆脱了波浪线,而无需使用感觉有点脏的变量技巧。

while (!token.IsCancellationRequested)
{
var client = await m_server.AcceptTcpClientAsync().ConfigureAwait(false);

Client c = new Client(client);

NonAsync(c);
}

public static void NonAsync(VClient vc)
{
Task.Run(() => HandleClientAsync(vc));
}

方法 4:将 HandleClientAsync 设为 Async void 而不是 Async Task(非常糟糕)

public static async Task HandleClientAsync(Client c)
// Would change to
public static async Void HandleClientAsync(Client c)

问题:

  • 执行即发即弃任务时使用 Task.Run() 是否更好?
  • 您是否刚刚接受了您需要使用 var _ = FireAndForget() 技巧来实现即发即弃?我可以忽略警告,但感觉有些不对劲。
  • 如果我想从客户端更新我的用户界面,我该怎么做?我会只使用调度员吗?

谢谢大家

最佳答案

我从来都不喜欢后台工作人员,您希望它在任务中运行很长时间。任务被安排在从池中提取的线程上运行。当您安排这些长时间运行的任务时,线程池会变得越来越小。最终池中的所有线程都忙于运行您的任务,事情变得非常缓慢且难以管理。

我在这里的推荐?使用 Thread class并自己管理它们。通过这种方式,您可以将线程池​​和任务的开销排除在外。

附录 - 生产者消费者模型

另一个需要考虑的有趣问题:您真的需要为每个客户端创建一个线程吗?就内存开销而言,线程的创建和维护成本相当高,如果您的客户端交互使得客户端线程将绝大部分时间花在等待某事上,那么可能是 producer consumer模型更适合您的用例。

例子:

  • 客户端连接到监听线程,被放入客户端队列
  • 负责检查客户端是否需要任何东西的工作线程经常通过该队列并检查 - 客户端是否有新消息需要服务?如果是这样,它将为客户端的所有消息提供服务,然后继续

通过这种方式,您可以将工作线程的数量限制为管理消息队列所需的数量。您甚至可以根据所有客户端得到服务的时间长度动态添加工作线程。

如果你坚持

如果您真的喜欢您的工作,我建议您稍微重构一下您正在做的事情,这样您就可以做一些更类似于 CreateServiceForClient(c) 的事情;

这可能是一个同步 方法,返回类似 ClientService 的内容。然后,ClientService 可以创建执行 HandleClientAsync 现在执行的操作的任务,并将该任务存储为成员。它还可以提供像ClientService.WaitUntilEnd()和ClientService.Disconnect()(可以设置取消 token ,也存储为成员变量)

关于c# - 理解使用无限循环时的即发即忘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42310542/

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