C # Как мне остановить процесс tcpClient.Connect (), когда я буду готов к завершению программы? Он просто сидит как 10 секунд! - PullRequest
4 голосов
/ 28 апреля 2009

Это одна из моих первых проблем. Всякий раз, когда я выхожу из программы, tcpClient.Connect () закрывается навсегда. Я перепробовал кучу вещей, но ни одна из них, похоже, не работает.

Взгляните на поток CreateConnection (), если клиент еще не подключен ... и я закрываю программу, закрытие занимает целую вечность. Если он подключен, он немедленно закрывается. Я знаю, что это можно сделать с помощью какого-то трюка с тайм-аутом, но я попробовал несколько, и ни один из них не сработал.

Пожалуйста, предоставьте пример кода, если можете.

Кроме того, есть ли хороший учебник для C # по чтению / записи реальных байтов с буфером вместо этой версии, который просто выполняет masterServer.writeLine () и masterServer.readline (), или они оба столь же эффективны?

Если вы видите что-нибудь еще, чтобы помочь мне улучшить это ... во что бы то ни стало, продолжайте. Я пытаюсь научить себя, как это сделать, и у меня нет помощи, поэтому не позволяйте мне продолжать делать что-то не так, если вы видите это !!! Спасибо, ребята!

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

    }
}

Ответы [ 3 ]

8 голосов
/ 22 сентября 2010

Извините, после тестирования: НЕТ, он не использует асинхронную ручку ожидания, он блокирует процесс: (

Я предпочитаю это решение, которое также блокирует процесс, но только на указанный вами период, в данном случае 5 секунд:

using (TcpClient tcp = new TcpClient())  
{  
    IAsyncResult ar = tcp.BeginConnect("127.0.0.1", 80, null, null);  
    System.Threading.WaitHandle wh = ar.AsyncWaitHandle;  
    try 
    {  
       if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false))  
       {  
           tcp.Close();  
           throw new TimeoutException();  
       }  

        tcp.EndConnect(ar);  
    }  
    finally 
    {  
        wh.Close();  
    }  
}

От: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/2281199d-cd28-4b5c-95dc-5a888a6da30d

В следующем примере используются как асинхронное соединение, так и асинхронное управление тайм-аутом:

var tcp = new TcpClient();
var ar = tcp.BeginConnect(Ip, Port, null, null);
Task.Factory.StartNew(() =>
{
    var wh = ar.AsyncWaitHandle;
    try
    {
        if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false))
        {
            // The logic to control when the connection timed out
            tcp.Close();
            throw new TimeoutException();
        }
        else
        {
            // The logic to control when the connection succeed.
            tcp.EndConnect(ar);
         }
     }
     finally
     {
         wh.Close();
     }
});
5 голосов
/ 05 декабря 2009

соединение с таймаутом 2000 мс:

AutoResetEvent connectDone = new AutoResetEvent( false );
TcpClient client = new TcpClient();
client.BeginConnect(
    "127.0.0.1", 80,
    new AsyncCallback(
        delegate( IAsyncResult ar ) {
            client.EndConnect( ar );
            connectDone.Set();
        }
    ), client
);
if( !connectDone.WaitOne( 2000 ) ) {
    Console.WriteLine( "network connection failed!" );
    Environment.Exit( 0 );
}
Stream stream = client.GetStream();
1 голос
/ 28 апреля 2009

Добавление проверки в процессе подключения, чтобы отменить ее, если программа завершается, должно помочь.

Попробуйте добавить это в CreateConnection() внутри цикла while(!success), но перед блоком try:

if(RequestExitConnectionThread)
{
    break;
}

Вот пример асинхронного вызова BeginConnect ():

myTcpClient.BeginConnect("localhost", 80, OnConnect, null);

Функция OnConnect:

public static void OnConnect(IAsyncResult ar)
{
    // do your work
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...