“代理到一个实例方法不能为空”这个“同时转发事件 [英] "Delegate to an instance method cannot have null 'this' " while forwarding an event

查看:140
本文介绍了“代理到一个实例方法不能为空”这个“同时转发事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从类客户端转发类 OnClientMessage 在类服务器到我的文库外面。

Im trying to forward an event OnClientMessage from my class Client over the class Server to outside my libary.

Client.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);
    }
}

Server.cs / p>

Server.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();
    }
}

现在当事件触发时,应用程序崩溃, code>委托给一个实例方法不能有null'this'。

我正在做错事,或者这不是转发事件的正确方法?

Now when the event is firing the application crashes with Delegate to an instance method cannot have null 'this'.
Are I'm doing something wrong or isn't this the right way to forward an event?

推荐答案

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

This is pretty unique, never once seen anybody do this. It is a regression in the .NET Framework, 3.5 gives you a much better exception. Basic problem is that you made the event subscribe itself. A simple version to repro that crash:

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()方法。

You are not actually "forwarding" the event. Untangle your names and code. Add, say, a Fire() method.

这篇关于“代理到一个实例方法不能为空”这个“同时转发事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆