转发事件时,“委托给实例方法不能有空的'this'”

本文关键字:不能 this 实例方法 事件 转发 | 更新日期: 2023-09-27 17:57:07

我试图将我的类Client中的事件OnClientMessage转发到我的Server之外。

客户端.cs

public class Client
{
    private TcpClient tcpClient;
    private StreamWriter writer;
    private Boolean alive = true;
    private int id;
    public delegate void OnClientMessageHandler(Client sender, String message);
    public delegate void OnClientDisconnectHandler(Client sender);
    public event OnClientMessageHandler OnClientMessage;
    public event OnClientDisconnectHandler OnClientDisconnect;
    public Client(TcpClient tcpClient, int id)
    {
        this.tcpClient = tcpClient;
        this.id = id;
        writer = new StreamWriter(tcpClient.GetStream());
        new Thread(() =>
        {
            Listen(new StreamReader(tcpClient.GetStream()));
        }).Start();
    }
    void Listen(StreamReader reader)
    {
        while (tcpClient.GetStream().DataAvailable && alive)
        {
           OnClientMessage(this, reader.ReadLine());
           Thread.Sleep(150);
        }
    }
    public void Write(String message)
    {
        writer.WriteLine(message);
        writer.Flush();
    }
    public int GetID()
    {
        return id;
    }
    public void Close()
    {
        alive = false;
        writer.Close();
        tcpClient.Close();
        OnClientDisconnect(this);
    }
}

服务器.cs

public class Server
{
    private IPAddress serverIP;
    private short serverPort;
    private TcpListener serverListener;
    private int serverClientCount;
    public List<Client> serverClients = new List<Client>();
    private Boolean running;
    public delegate void OnClientMessageHandler(Client sender, String message);
    public delegate void OnClientDisconnectHandler(Client sender);
    public event OnClientMessageHandler OnClientMessage;
    public event OnClientDisconnectHandler OnClientDisconnect;
    public Server(IPAddress ip, short port, Boolean autoStart = true)
    {
        this.serverIP = ip;
        this.serverPort = port;
        if(autoStart)
            OpenServer();
    }
    public void OpenServer()
    {
        serverListener = new TcpListener(serverIP, serverPort);
        serverListener.Start();
        running = true;
        while (running)
        {
            if (serverListener.Pending())
            {
                TcpClient tcpClient = serverListener.AcceptTcpClient();
                new Thread(() =>
                {
                    Client client;
                    client = new Client(tcpClient, serverClientCount);
                    client.OnClientMessage += new Client.OnClientMessageHandler(OnClientMessage);
                    client.OnClientDisconnect += new Client.OnClientDisconnectHandler(OnClientDisconnect);
                    serverClients.Add(client);
                    serverClientCount++;
                }).Start();
            }
            else
            {
                Thread.Sleep(150);
            }
        }
    }
    public void WriteToClient(Client client, String message)
    {
        client.Write(message);
    }
    public void WriteToAll(String message)
    {
        serverClients.ForEach(client => client.Write(message));
    }
    public void Shutdown()
    {
        running = false;
        serverClients.ForEach(client => client.Close());
        serverListener.Stop();
    }
}

现在,当事件触发时,应用程序崩溃并显示Delegate to an instance method cannot have null 'this' .
我做错了什么,还是这不是转发事件的正确方式?

转发事件时,“委托给实例方法不能有空的'this'”

这是

非常独特的,从来没有见过有人这样做。 这是.NET Framework中的回归,3.5为您提供了一个更好的例外。 基本问题是你让事件订阅了自己。 重现崩溃的简单版本:

using System;
class Program {
    public static event Action Kaboom;
    static void Main(string[] args) {
        Kaboom += new Action(Kaboom);    // 3.5 raises an exception here
        var handler = Kaboom;
        if (handler != null) handler();  // kaboom
    }
}

您实际上并没有"转发"事件。 解开您的姓名和代码。 例如,添加一个 Fire() 方法。