【问题标题】:C# - C:stop blocking listen socket on a child threadC# - C:停止在子线程上阻塞监听套接字
【发布时间】:2015-12-01 04:30:47
【问题描述】:

我的程序:
我创建了 2 个线程:线程 1 带有一个监听套接字,线程 2 做一些事情。
但是线程 1 阻塞了程序,我无法启动线程 2,直到线程 1 上的侦听套接字接收到数据。 但我需要 2 个线程同时运行,并且不需要在 2 个线程之间保持同步。(但仍在同一个程序中)。
怎么做??? 我的代码是这样的:

Thread thread1 = new Thread(new ThreadStart(a.thread1));
Thread thread2 = new Thread(new ThreadStart(b.thread2));
try
            {
                thread1.Start();
                thread2.Start();
                thread1.Join();   // Join both threads with no timeout
                                  // Run both until done.
                thread2.Join();
            }

程序在线程 1 处停止(监听套接字)。
而且我不想使用非阻塞套接字(我正在使用阻塞套接字)。
监听套接字应该阻塞子线程,但不应该阻塞我的程序。

【问题讨论】:

    标签: c# multithreading sockets asyncsocket


    【解决方案1】:

    我最近遇到了同样的问题,并像这样解决了它:

        private static void StartServers()
    {
        for (int i = Convert.ToInt32(ConfigurationManager.AppSettings.Get("PortStart"));
                        i <= Convert.ToInt32(ConfigurationManager.AppSettings.Get("PortEnd"));
                        i++)
                    {
                        var localAddr = IPAddress.Parse(ConfigurationManager.AppSettings.Get("IpAddress"));
                        var server = new TcpListener(localAddr, i);
                        Servers.Add(server);
                        server.Start();
                        StartAccept(server);
                    }
    }
    private static void StartAccept(TcpListener server)
        {
            server.BeginAcceptTcpClient(OnAccept, server);
        }
    private static void OnAccept(IAsyncResult res)
        {
            var client = new TcpClient();
            try
            {
                Console.ForegroundColor = Console.ForegroundColor == ConsoleColor.Red
                    ? ConsoleColor.Green
                    : ConsoleColor.White;
                var server = (TcpListener) res.AsyncState;
                StartAccept(server);
                client = server.EndAcceptTcpClient(res);
                Console.WriteLine("Connected!\n");
                var bytes = new byte[512];
                // Get a stream object for reading and writing
                var stream = client.GetStream();
    
    
                int i;
    
                // Loop to receive all the data sent by the client.
                while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    // Translate data bytes to a ASCII string.
                    var data = Encoding.ASCII.GetString(bytes, 0, i);
                    Console.WriteLine("Received: {0} \n", data);
    
                    // Process the data sent by the client.
                    data = InterpretMessage(data);
                    var msg = Encoding.ASCII.GetBytes(data);
    
                    // Send back a response.
                    stream.Write(msg, 0, msg.Length);
                    Console.WriteLine("Sent: {0} \n", data);
                }
            }
            catch (Exception exception)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                client.Close();
                Console.WriteLine(exception.Message);
            }
        }
    

    基本上这样做是创建一个异步接收系统,您可以在其中让多个服务器同时监听多个端口。请记住,每个端口只能有一个侦听器。

    在您的示例中,您可以简单地调用 StartServers 方法,然后直接继续执行您的应用程序正在执行的任何操作。

    为了让这在单个端口上的单个服务器上工作,只需删除 StartServers 中的循环并配置 1 个 TcpListener 并启动它。

    【讨论】:

    • 我们不能使用非阻塞线程同步套接字吗???(只等待停止1个进程,而不是程序)
    • 您现在的问题不是您的线程在侦听器接收数据之前一直阻塞吗?同步操作阻塞线程,因此也阻塞连接的线程。也许我应该提出一个更好的问题,如果线程在独立工作,为什么要加入?通过加入两个线程,您可能不会创建竞争条件吗?你是不是想做this之类的事情
    • 我看到:当使用 Thread1.join() 时,程序将被阻塞,直到 thread1(listen socket) 完成。但是如果我不将线程 1 加入到程序中,我可以得到线程的结果吗???(线程 1 会为我改变一些值)
    • 假设类值是静态的或者你的类是单例的,那么你应该可以。请记住,您不是线程安全的,如果您的阻塞策略错误,您可能会遇到竞争条件。正如您从链接中的示例中看到的那样,程序将等待线程 2 完成,基本上线程 1 对共享数据所做的任何更改都应该可供线程 2 使用。
    猜你喜欢
    • 2012-06-13
    • 1970-01-01
    • 2010-11-09
    • 2011-11-14
    • 2017-01-11
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 2017-01-16
    相关资源
    最近更新 更多