C# StreamWriter ReadLine方法挂起程序

C# StreamWriter ReadLine方法挂起程序,c#,asynchronous,streamwriter,C#,Asynchronous,Streamwriter,我正在尝试在C#中使用一些基本的多线程。我发现没有明确的教程,所以请容忍我的低标准代码: class Program { private static TcpListener listener; private static List<TcpClient> clients; static void Main(string[] args) { listener = new TcpListener(IPAddress.Any, 1337)

我正在尝试在C#中使用一些基本的多线程。我发现没有明确的教程,所以请容忍我的低标准代码:

class Program
{
    private static TcpListener listener;
    private static List<TcpClient> clients; 
    static void Main(string[] args)
    {
        listener = new TcpListener(IPAddress.Any, 1337);
        clients = new List<TcpClient>();
        StartListening();
        Console.WriteLine("Accepting clients..");
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    static async void StartListening()
    {
        listener.Start();
        while (true)
        {
            clients.Add(await listener.AcceptTcpClientAsync().ConfigureAwait(false));
            Console.WriteLine("Client connected!");
            HandleClient(clients[clients.Count - 1], clients.Count);
        }
    }

    static async void HandleClient(TcpClient c, int number)
    {
        Console.WriteLine($"Getting client #{number}'s handshake..");
        var ns = c.GetStream();
        var sr = new StreamReader(ns);
        var handshake = sr.ReadLine();
        Console.WriteLine("Client {0}'s handshake: {1}", number, handshake);
    }
}
接受客户端部分可以工作,但是程序仅在
HandleClient()
的第一行之后停止。我尝试过等待荒谬的时间量(1000毫秒),但即使如此,它也没有收到任何东西,也没有抛出异常(即,它保持连接)。我做错了什么


客户端代码是如果你需要它

您的客户端代码在此被破坏-您永远不会刷新它:

var sw = new StreamWriter(ns);
Thread.Sleep(1000);
sw.WriteLine(handshake);
无需调用
线程.Sleep
调用,但如果希望数据立即实际发送到网络层,则应刷新
StreamWriter

sw.Flush();

虽然(正如Stephen Cleary所指出的)这并不意味着它必须立即发送,但有理由期望它在刷新后“很快”发送。

正如Jon Skeet所提到的,要确保内容不只是放在缓冲区中,您应该刷新它

您的客户应该是这样的:

var sw = new StreamWriter(ns);
Thread.Sleep(1000); // let the server catch up
sw.WriteLine(handshake);
sw.Flush();
Console.WriteLine("Staying connected.. Press ESCAPE to exit.");
编辑:忘了提。。。那
线程睡眠(1000)那里。。。您可以安全地将其移除

我正在尝试在C#中使用一些基本的多线程

我总是对那些试图通过编写裸机TCP/IP服务器来学习并发性的开发人员感到惊讶(他们以前从未编程过TCP/IP)。并发和TCP/IP是两个非常困难的主题;同时试图学习它们几乎肯定会以灾难告终。这真的很奇怪,这是一个如此普遍的方法

如果您想学习异步,我推荐我的and(其中,您将学习“避免
异步无效”
)原则

如果你想学习TCP/IP,我推荐我的。但是,编写TCP/IP代码几乎是不必要的,因为您可以同时更改客户端和服务器,所以我强烈建议改用signar

我怀疑您实际上想学习
async
,而TCP/IP只是一个障碍。因此,抛开较难的话题(TCP/IP),将
async
与WebAPI或SignalR等更简单的通信结合使用


(就您看到的实际问题而言,它确实是由缓冲引起的,但需要注意的是,刷新缓冲不会导致数据立即通过网络发送;它只会立即发送到网络层。正确的解决方案需要消息帧。)

您也应该发布发送数据的客户端代码,因为没有它,问题就不完整了。既然问题也在客户端,而不是服务器端,那么这就更重要了。@LasseV.Karlsen我同意!爱你,乔恩!你是我的英雄:)事实上,我正在编写一个多人蛇游戏,所以我需要TCP/IP和异步:)@Ilan321:Signal对多人游戏非常有效。是的,但我无法导入任何外部库:(@Ilan321:不知道你的意思。作为一个与TCP/IP具有同等功能的传输协议,Signal应该足够了。我不能实际使用任何未包含在.NET 4.5中的库..:(
var sw = new StreamWriter(ns);
Thread.Sleep(1000); // let the server catch up
sw.WriteLine(handshake);
sw.Flush();
Console.WriteLine("Staying connected.. Press ESCAPE to exit.");