如果我在不同的线程上同步运行,它是不是会使其总体异步?

Posted

技术标签:

【中文标题】如果我在不同的线程上同步运行,它是不是会使其总体异步?【英文标题】:If i run syncroniously on different threads does it makes it async per total?如果我在不同的线程上同步运行,它是否会使其总体异步? 【发布时间】:2012-04-29 00:31:45 【问题描述】:

我想知道如果我在其他线程上同步运行我的应用程序是否会异步获取字符串?

我实际上并不知道如何使用 BeginSend/BeginReceive,所以我在不同的线程上使用了 socket.Send(...)、socket.Receive(...),这是否会使我的应用程序模拟异步连接。

顺便说一句,如果字符串大于缓冲区的大小会发生什么?对于客户端,我使用了 telnet,但是 telnet 实际上会在字符串从键盘获取时立即发送,所以我实际上不能超过缓冲区的大小,但是如果我使用另一个发送完整字符串的客户端呢?有没有办法告诉程序我发送的比缓冲区允许的多(通过我的变量recv 这是socketReceive的结果)?

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace CSharp_Console_Application

    class Program
    
        delegate Socket GetClients();
        static GetClients newClients;
        static List<Socket> clients;

        static ManualResetEvent allDone = new ManualResetEvent(false);

        static void Main(string[] args)
        
            IPEndPoint serverIPEP = new IPEndPoint(IPAddress.Any, 9080);
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(serverIPEP);
            serverSocket.Listen(10);

            Console.WriteLine("Waiting for connections...");

            clients = new List<Socket>();

            newClients = () =>
                
                    Socket clientSocket = serverSocket.Accept();
                    IPEndPoint clientIPEP = (IPEndPoint)clientSocket.RemoteEndPoint;

                    Console.WriteLine("Connected to 0.", clientIPEP);

                    clients.Add(clientSocket);

                    SendString("Welcome to my server!", clientSocket);
                    return clientSocket;
                ;

            while (true)
            
                allDone.Reset();

                newClients.BeginInvoke((itfAR) =>
                    
                        allDone.Set();

                        AsyncResult ar = (AsyncResult)itfAR;
                        GetClients invokedDelegate = (GetClients) ar.AsyncDelegate;

                        Socket clientSocket = invokedDelegate.EndInvoke(itfAR);
                        IPEndPoint clientIPEP = (IPEndPoint)clientSocket.RemoteEndPoint;

                        Console.WriteLine("Sent 'Welcome!' to 0.", clientIPEP);

                        string currentString = "";
                        while (true)
                        
                            currentString += ReceiveString(clientSocket);
                            if (currentString.Contains('\n'))
                            
                                Console.Write(clientIPEP + " said: " + currentString);

                                List<Socket> clientsWithoutThis = new List<Socket>();
                                clientsWithoutThis.AddRange(clients);
                                clientsWithoutThis.Remove(clientSocket);
                                SendToAll(clientsWithoutThis, currentString);

                                currentString = "";
                            
                        
                    ,
                    null);

                allDone.WaitOne();
            
        

        static void SendToAll(List<Socket> clients, string message)
        
            byte[] data = new byte[1024];
            clients.ForEach(clientSocket =>
                
                    IPEndPoint clientIPEP = (IPEndPoint)clientSocket.RemoteEndPoint;
                    data = Encoding.ASCII.GetBytes(clientIPEP + " said: " + message + "\r");
                    clientSocket.Send(data, data.Length, SocketFlags.None);
                );
        

        static void SendString(string message, Socket clientSocket)
        
            byte[] data = new byte[1024];
            data = Encoding.ASCII.GetBytes(message + "\n\r");
            clientSocket.Send(data, data.Length, SocketFlags.None);
        

        static string ReceiveString(Socket clientSocket)
        
            byte[] data = new byte[1024];
            int recv = clientSocket.Receive(data, data.Length, SocketFlags.None);

            if (recv < 1)
                return null;

            string receivedString = Encoding.ASCII.GetString(data, 0, recv);
            return receivedString;
        
    

【问题讨论】:

我可以问一下,当你想发送和接收异步时,为什么不使用异步方法? @Thanatos 你问如果字符串大于缓冲区会发生什么?好吧,TCP 不保证 1 次发送等于 1 次接收。那么,当您在 1 次接收中没有收到完整的字符串时会发生什么?当需要 2 或 3 次接收才能接收到您在服务器上发送的 1 次发送的相同字符串时会发生什么?这与 1 次发送大于缓冲区大小的情况相同。 【参考方案1】:

这样你的ManualResetEvent 往往是没用的。一旦你阻塞了主线程,你就会在BeginInvoke 的第一行调用set() 来释放。然后您再次将其重置为等待状态,但另一个BeginInvoke 调用将解除对代码的阻塞,而另一个BeginInvoke 可能仍在运行。所以最终你会有多个 BeginInvoke 线程,最终你会遇到多个异常或内存不足的错误。

【讨论】:

以上是关于如果我在不同的线程上同步运行,它是不是会使其总体异步?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 subView 中添加 UILabel 会使其像素化

linux 挂起进程

什么词是指可以由两个不同的线程同时/并行执行的代码段/功能?

如何同步线程中的 2 个进程以便它们一起运行?

从 pthread 调用 sleep() 是不是会使线程进入睡眠状态或进程?

.Net - 线程本地变量(存储)的使用