通过所有异步/等待(来自线程池)的工作,我遇到了一个有趣的挑战。
我有一个在WPF应用程序中运行的TCP Server,该服务器接受客户端并将其存储在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()
。在任何给定时间,我实际上可能只有1个或2个客户端正在发送数据,因此我不能
WhenAll()
,并且尝试了WhenAny()
和WaitAny()
都没有成功。请注意未来的Google员工:
WaitAny()
就像Wait()
一样,并且已被屏蔽。不要在UI线程上执行此操作。而是使用WhenAny()
并等待它。因此,我目前的实现方式是可行的,但我无法弄清楚该错误,即如果其他客户端不发送数据,则消息将从一个客户端建立。
TL; DR:我是否正确使用
WhenAny()
还是有更好的方法让我等待ReadLineAsync并将结果传递到文本框?编辑:这是我所看到的行为
我按以下顺序输入:左,右,左2,右2,左3,右3
好像有些邮件被丢弃了吗?
编辑2:我找到了我在MSDN博客上复制的代码段的来源:https://blogs.msdn.microsoft.com/pfxteam/2012/08/02/processing-tasks-as-they-complete/
此代码段专门用于遍历一系列任务,以确保所有任务均已完成。我不在乎任务是否重复,因此我需要修改代码以始终检查整个任务列表,而不是删除任何任务。
最佳答案
好像有些消息被丢弃了吗?
是。因为异步工作是在您调用其方法(例如ReadLineAsync
)时启动的。当其中一个完成时(Task.WhenAny
),您的代码将放弃其他任务。但是他们继续运行-他们仍在从套接字中读取内容,所读取的内容都将被丢弃。
AFAIK,当您再次从同一套接字开始读取时,行为是不确定的-可能读取下一个内容,或者可能将其排队。我确实知道您不应该同时从套接字(或任何流)发出多次读取。
套接字不是async
的理想选择,因为它们可以随时发送数据。您应该改用Rx或事件。可以使async
工作,但这非常复杂。
关于c# - 如何使用Task.WhenAny和ReadLineAsync从任何TcpClient获取数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42116277/