正确的线程管理方式

时间:2016-05-11 08:36:22

标签: c# multithreading sockets

我正在构建一个C#套接字服务器。我的代码目前有效,但我不确定这是否是正确的方法。

当连接TcpClient时,我将其放入一个具有以下方法的新对象中,然后调用Init()开始检查数据是否可用,数据何时可用我调用的事件是I听取我使用我创建的方法(如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)并删除Init()中的Read(),然后再根据需要再次致电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;
        }
    }

1 个答案:

答案 0 :(得分:1)

读取套接字的正确方法是从中读取。在数据准备好之前,呼叫将无法完成。没有必要举办活动。 Available属性几乎总是一个bug,所以不要使用它。

执行:

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

立即。可以在后台线程上运行它(与注释中建议的相反)。一旦你有太多的线程,线程就成了问题。如果只保留几十个套接字连接,那就没有问题了。

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

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

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