通过我的方式完成所有异步/等待(来自线程池),我遇到了一个有趣的挑战。
我有一个在 WPF 应用程序中运行的 TCP 服务器,它接受客户端并将它们存储在List<>
像这样:
private List<Client> clients = new List<Client>();
while (running && clientCount <= maxClients)
{
Client client = new Client(await server.AcceptTcpClientAsync());
await client.WriteLineAsync("Connected to the Server!");
clients.Add(client);
clientCount++;
}
所以我想做的是遍历我的客户列表,如果收到任何数据,我想将其附加到文本框。我意识到这可能不是最好的方法为了实现这一目标,我愿意接受建议,但这就是我目前的结构。
一键启动循环,不断调用和等待AllReadLineAsync()
private async void btnStartReadLoopClick(object sender, RoutedEventArgs e)
{
btnStartReadLoop.IsEnabled = false;
while(server.clientCount > 0)
{
string text = await server.AllReadLineAsync();
txtOutputLog.AppendText("[client] " + text + "\n");
}
}
这是这个函数:
public async Task<string> AllReadLineAsync()
{
var tasklist = new List<Task<string>>();
foreach (var client in clients)
tasklist.Add(client.ReadLineAsync());
while (tasklist.Count > 0)
{
Task<string> finishedTask = await Task.WhenAny(tasklist);
if (finishedTask.Status == TaskStatus.RanToCompletion)
return await finishedTask;
tasklist.Remove(finishedTask);
}
return "Error: No task finished";
}
该函数遍历客户端列表并创建一个List<Tast<string>>
所有的ReadLineAsync()
tasks.
在任何给定时间,我可能只有 1 或 2 个客户端实际发送数据,所以我不能WhenAll()
我试过了WhenAny()
and WaitAny()
没有成功。
未来的谷歌用户请注意: WaitAny()
就好像Wait()
并且正在阻塞。不要在 UI 线程上执行此操作。而是使用WhenAny()
并等待它。
因此,我当前的实现是可行的,但我无法弄清楚如果其他客户端不发送数据,消息将从 1 个客户端构建的错误。
TL;DR:我正在使用吗WhenAny()
正确还是有更好的方法让我等待 ReadLineAsync 并将结果传递到文本框?
EDIT:这是我看到的行为
我按以下顺序输入:左、右、左 2、右 2、左 3、右 3
似乎有些消息被丢弃了?
![enter image description here](https://i.stack.imgur.com/hcqxe.png)
EDIT 2:我在MSDN博客上找到了我复制的代码片段的来源:https://blogs.msdn.microsoft.com/pfxteam/2012/08/02/processing-tasks-as-they-complete/
此代码片段专门用于迭代任务列表,确保它们全部完成。我不关心任务是否重复,所以我需要修改代码以始终检查整个任务列表,而不是删除任何任务。