【问题标题】:Correct way of managing threads管理线程的正确方法
【发布时间】:2016-05-11 08:36:21
【问题描述】:

我正在构建一个 C# Socket 服务器。我的代码目前可以工作,但我不确定这是否是正确的方法。

TcpClient 连接时,我使用以下方法将它放入一个新对象中,然后调用Init() 开始检查数据是否可用,当数据可用时,我调用我监听的事件开始使用我创建的方法读取缓冲区,例如ReadInt32(), ReadByte(), ReadString() ReadObject<T>()

    public void Init()
    {
        ThreadPool.QueueUserWorkItem(Read);
    }

    private void Read(object state)
    {
        if (IsClientConnected())
        {
            if (_connected.Available > 0)
            {
                OnDataAvailable(_connected.Available);
            }
            Init();
        }
    }

我应该在这里使用While 循环还是应该像现在一样重新启动Init()?那我应该使用BackgroundWorkerThreadTask 而不是ThreadPool

我还考虑将Init() 更改为BeginWait(some sort of callback here) 并删除Read() 中的Init(),然后在需要时再次调用BeginWait

我的目的是听命令并回复命令。同时连接了 x 个客户端。

所以场景如下:

我有一个连接到服务器的应用程序。 然后,服务器使用 TcpClient 作为构造函数中的参数初始化一个新对象。然后服务器将连接的客户端添加到另一个客户端的房间。这个房间监听每个客户的事件DataAvailable看下面

    private void Client_DataAvailable(ClientWrapper sender, int data)
    {
        var command = (Commands)Client.ReadByte();
        switch (command)
        {
            case Commands.RequestConnectId: // 1

                var buffer = new WriteBuffer(Commands.RequestConnectId);
                buffer.WriteInt32(sender.ConnectId);
                sender.Reply(buffer);

                break;
            case Commands.WriteText: //2

                var buffer = new WriteBuffer(Commands.WriteText);
                buffer.WriteString(sender.ReadString());
                BroadCast(sender.ConnectId,buffer);//Send to the other client

                break;
        }
    }

【问题讨论】:

  • 在 C#5 中处理线程的正确方法是对 I/O 完全不使用线程。相反,您使用 asyncawait 来实现异步性。
  • 有什么建议可以应用asyncawait我正在编辑我的问题,并提供更多关于我在做什么的信息
  • 您的问题超出了 StackOverflow 中可接受问题的范围。不幸的是,我无法建议您哪个 SE 网络更适合这个问题。

标签: c# multithreading sockets


【解决方案1】:

读取套接字的正确方法是直接读取。在数据准备好之前,调用不会完成。不需要事件。 Available 属性几乎总是一个错误,所以不要使用它。

只需执行:

var command = (Commands)Client.ReadByte();

马上。可以在后台线程上运行它(与 cmets 中建议的相反)。一旦线程过多,线程就会成为问题。如果您只维护几十个套接字连接,那没有问题。

您也可以使用异步 IO,最好使用 await。同样的想法也适用:阅读即可。

如果您想处理命令流,只需将其包装在一个循环中:

while (true) {
 ReadCommand();
 WriteResponse();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 2014-01-15
    相关资源
    最近更新 更多