C# IRC Bot Error: 'Cannot read from a closed text reader'

C# IRC Bot Error: 'Cannot read from a closed text reader'

我以前用过一次这个代码,它起作用了。现在,每次它尝试连接到 IRC 服务器时,我都会收到错误消息:'Cannot read from a closed text reader'

为了隐私我已经更改了地址

这是我的代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace IRCBot
{
class Program
{

}
class IrcBot
{
    // Irc server to connect 
    public static string SERVER = "irc.rizon.net";
    // Irc server's port (6667 is default port)
    private static int PORT = 6660;
    // User information defined in RFC 2812 (Internet Relay Chat: Client Protocol) is sent to irc server 
    private static string USER = "irc_bot";
    // Bot's nickname
    private static string NICK = "BotNick";
    // Channel to join
    private static string CHANNEL = "#testing";
    // StreamWriter is declared here so that PingSender can access it
    public static StreamWriter writer;
    static void Main(string[] args)
    {
        NetworkStream stream;
        TcpClient irc;
        string inputLine;
        StreamReader reader;
        string nickname;
        try
        {
            irc = new TcpClient(SERVER, PORT);
            stream = irc.GetStream();
            reader = new StreamReader(stream);
            writer = new StreamWriter(stream);
            // Start PingSender thread
            PingSender ping = new PingSender();
            ping.Start();
            writer.WriteLine(USER);
            writer.Flush();
            writer.WriteLine("NICK " + NICK);
            writer.Flush();
            writer.WriteLine("JOIN " + CHANNEL);
            writer.Flush();
            while (true)
            {
                while ((inputLine = reader.ReadLine()) != null)
                {
                    if (inputLine.EndsWith("JOIN :" + CHANNEL))
                    {
                        // Parse nickname of person who joined the channel
                        nickname = inputLine.Substring(1, inputLine.IndexOf("!") - 1);
                        // Welcome the nickname to channel by sending a notice
                        writer.WriteLine("NOTICE " + nickname + " :Hi " + nickname +
                        " and welcome to " + CHANNEL + " channel!");
                        writer.Flush();
                        // Sleep to prevent excess flood
                        Thread.Sleep(2000);
                    }
                }
                // Close all streams
                writer.Close();
                reader.Close();
                irc.Close();
            }
        }
        catch (Exception e)
        {
            // Show the exception, sleep for a while and try to establish a new connection to irc server
            Console.WriteLine(e.ToString());
            Thread.Sleep(5000);
            string[] argv = { };
            Main(argv);
        }
    }
}

class PingSender
{
    static string PING = "PING :";
    private Thread pingSender;
    // Empty constructor makes instance of Thread
    public PingSender()
    {
        pingSender = new Thread(new ThreadStart(this.Run));
    }
    // Starts the thread
    public void Start()
    {
        pingSender.Start();
    }
    // Send PING to irc server every 15 seconds
    public void Run()
    {
        while (true)
        {
            IrcBot.writer.WriteLine(PING + IrcBot.SERVER);
            IrcBot.writer.Flush();
            Thread.Sleep(15000);
        }
    }
}

}

关闭所有流必须在外部 while:

 while (true)
            {
                while ((inputLine = reader.ReadLine()) != null)
                {
                   ....
                }            
            }
  // Close all streams
                writer.Close();
                reader.Close();
                irc.Close();

将所有流结束行移动到 "finally" 块:

try
{
...
}
catch (Exception e)
{
  Console.WriteLine(e.ToString());
  Thread.Sleep(5000);
  string[] argv = { };
  Main(argv);
}
finally 
{
  //Close all streams
  writer?.Close();
  reader?.Close();
  irc?.Close();
}

请注意,我使用了新的 C#6 空传播运算符 ?。这里导致你的流可以为空。如果您使用的是 C# ver<6,那么这样写: if (writer!=null) writer.Close();