c# - 如果我在不同的线程上同步运行,它会使每个线程异步吗?

标签 c# sockets asynchronous .net

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

我实际上并不知道如何使用 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;
        }
    }
}

最佳答案

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

关于c# - 如果我在不同的线程上同步运行,它会使每个线程异步吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10195117/

相关文章:

javascript - Redis 异步查询过早完成的可能解决方案

javascript - 如何在 javascript 中实现类似同步的行为?

c# - EF Linq 包括最后一个

c# - 本地化资源 .NET - 如何使它们保持同步?

linux 的 c++ 应用程序将 ipv4 数据包转换为 ipv6

sockets - fd ://mean exactly in dockerd -H fd://是什么意思

c# - EF6,Composite Key,注释够了吗?或者我还必须使用 Fluent API 吗?

c# - MemoryStream (pdf) 到 Ghostscript 到 MemoryStream (jpg)

javascript - socket.io http 在本地主机上监听

asp.net-core - .net Core **从不调用** "next.Invoke after the response has been sent to the client"那么如何实现符合良好实践的代码?