C # Come faccio a evitare che un oggetto TcpClient da disporre in un thread diverso ho creato con la nuova parola chiave?

StackOverflow https://stackoverflow.com/questions/795518

Domanda

Così sto cercando di fare un cliente per il mio assistente in C #, che accetta i messaggi come comandi in modo da poter controllare il client in remoto. Ho avuto problema dopo problema con la mia masterServer.Connect prendendo sempre al carico, e quasi ogni volta che chiudo la mia applicazione devo aspettare 10 secondi di fermarsi completamente. Ho provato di tutto per fermare questo ... senza fortuna. Così ho rinunciato a questo, e ora a fissare un altro problema che sto usando un Masterserver = new TcpClient (), che sembra funzionare abbastanza bene all'interno del filo CreateConnection (). Ma quando il filo è fatto, io chiamo il SendClientInfo () da qualche parte lungo la linea e il risultato e 'questo errore di runtime:

Impossibile accedere a un oggetto eliminato, System.Net.Sockets.TcpClient

Così ho fatto del mio meglio per trovare un modo di salvare l'oggetto prima che dispone o qualcosa, ma non riesco proprio a trovare il modo di farlo. Così qui sono le mie domande:

  1. Come posso evitare il server principale = new TcpClient () da smaltire in modo da poter usare quella sul mio SendClientInfo ()?
  2. Qualcuno può rielaborare il metodo mia CreateConnection () in modo da poter vedere come fare corretto? Ho riscritto quella cosa un migliaio di volte, e ancora sembra estremamente buggy e la masterServer.connect () vuole una vita per fare se non si è ancora connesso a un server.
  3. Le eventuali altre modifiche o correzioni si può vedere qui. Sono stato dentro e fuori questo per ore e ore solo cercando di insegnare a me stesso come utilizzare Sockets con la lettura come un centinaio di tutorial. Tutto quello che me che sto facendo male Ricorderò sempre mostrare e farlo correttamente la prossima volta.

Fatemi sapere se avete bisogno di più informazioni ... I really appreciate it.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace RemoteClient
{
    public partial class Form1 : Form
    {
        private int MyPort = 56789;
        private IPAddress myIp = IPAddress.Parse("210.232.115.79");
        private IPAddress serverIp = IPAddress.Parse("72.216.18.77"); // Master Server's IP Address
        public static TcpClient masterServer = new TcpClient();

        private StreamWriter responseWriter;
        private StreamReader commandReader;

        private Thread connectionThread;
        private Thread commandsThread;

        private bool RequestExitConnectionThread { get; set; }

        private delegate void AddMessageDelegate(string message, int category);
        private delegate void ConnectedDelegate();

        private bool isConnected { get; set; }

        public Form1()
        {
            InitializeComponent();
            isConnected = false;
        }

        private void LogMessage(string message, int category)
        {
            if (category == 1)
            {
                ListViewItem item = new ListViewItem(message);
                item.BackColor = Color.LightGreen;
                item.UseItemStyleForSubItems = true;
                Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString());
            }
            if (category == 2)
            {
                ListViewItem item = new ListViewItem(message);
                item.BackColor = Color.Orange;
                item.UseItemStyleForSubItems = true;
                Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString());
            }
            if (category == 3)
            {
                ListViewItem item = new ListViewItem(message);
                item.BackColor = Color.Yellow;
                item.UseItemStyleForSubItems = true;
                Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString());
            }
            if (category == 0)
            {
                Log.Items.Add(message).SubItems.Add(DateTime.Now.ToString());
            }
        }

        private void Connected()
        {
            LogMessage("Found and Accepted Master Server's connection. Waiting for reply...",1);
            Status.Text = "Connected!";
            Status.ForeColor = Color.Green;

            commandsThread = new Thread(new ThreadStart(RecieveCommands));

            sendClientInfo();
        }

        private void exitButton_Click(object sender, EventArgs e)
        {
            Disconnect();
            exitButton.Enabled = false;
            exitButton.Text = "Closing...";

            if (connectionThread != null)
            {
                while (connectionThread.IsAlive)
                {
                    Application.DoEvents();
                }
            }

            this.Close();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Connect();
        }

        private void Disconnect()
        {
            RequestExitConnectionThread = true;

            if (masterServer != null)
                masterServer.Close();

            if (connectionThread != null)
                connectionThread.Abort();

            LogMessage("Closing Client. Please wait while Program threads end.", 2);
        }

        private void Disconnected()
        {
            Status.Text = "Disconnected";
            Status.ForeColor = Color.Red;
            Connect();
        }

        private void Connect()
        {
            LogMessage("Attempting to connect to Master Server...", 1);

            connectionThread = new Thread(new ThreadStart(CreateConnection));
            connectionThread.Start();
        }

        private void CreateConnection()
        {
            int i = 1;
            bool success = false;

            while (!success)
            {
                try
                {
                    using (masterServer = new TcpClient())
                    {
                        IAsyncResult result = masterServer.BeginConnect(serverIp, MyPort, null, null);
                        success = result.AsyncWaitHandle.WaitOne(1000, false);
                    }

                    if (success)
                    {
                        BeginInvoke(new ConnectedDelegate(this.Connected), new object[] {});
                        break;
                    }
                    else
                    {
                        Thread.Sleep(2000);
                        BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Connection Retry # " + i.ToString() + ". Master Server hasn't been started yet.", 3 });
                    }
                }
                catch
                {
                    MessageBox.Show("Error!");
                }
                i++;
            }

        }

        private void RecieveCommands()
        {
            MessageBox.Show("Hello!");
            commandReader = new StreamReader(masterServer.GetStream());

            string CommandResponse = commandReader.ReadLine();
            string Command = null;

            if (CommandResponse != null)
                MessageBox.Show("Recieved Command that was NOT null!");

            if (CommandResponse != null)
            {
                MessageBox.Show("Recieved null response!");
                BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Disconnected From Master Server. Reason: Recieved Null response.", 1 });
                Disconnected();
            }
            else if (CommandResponse.StartsWith("0"))
            {
                MessageBox.Show("Recieved 0 as a response!");
                Command = CommandResponse.Substring(2).Trim();

                isConnected = false;
                BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Disconnected From Master Server. Reason: " + Command, 1 });
            }
            else if (CommandResponse.StartsWith("1"))
            {
                MessageBox.Show("Recieved 1 as a response!");
                isConnected = true;
                BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Connected to Master Server Successfully.", 1 });
            }
        }


        //************************** RESPONSE'S BELOW HERE ************************* \\

        private void sendClientInfo()
        {
            responseWriter = new StreamWriter(masterServer.GetStream());

            responseWriter.WriteLine(myIp.ToString());
            responseWriter.Flush();
        }

    }
}
È stato utile?

Soluzione

In questo caso non si dovrebbe usare un blocco using. In realtà, a meno che non ci sono alcuni scenari selvaggi che non vengono in mente, non usare mai un blocco using su una variabile che viene dichiarata al di fuori di tale ambito. Il blocco using chiama il metodo Dispose() al completamento del blocco, che è il motivo per cui il server è in via di dismissione. Basta cambiare il codice per rimuovere il blocco e si dovrebbe essere tutto a posto. In questo modo:

masterServer = new TcpClient();

IAsyncResult result = masterServer.BeginConnect(serverIp, MyPort, null, null);
success = result.AsyncWaitHandle.WaitOne(1000, false);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top