如何检查我是否已连接? [英] How to check if I'm connected?

查看:56
本文介绍了如何检查我是否已连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

全部,我正在编写一个需要与服务器建立异步阻止连接的应用程序.我有一个带有按钮的GUI窗体和一个与BeginConnect/EndConnect对执行连接的类.该实现遵循 MSDN示例.

ALL, I am writing an application that will need to have an asynchronous blocking connection to the server. I have a GUI Form with the button and a class that performs a connection with BeginConnect/EndConnect pair. The implementation follows this MSDN example.

但是,在回调方法中抛出了thw异常.这就是我要避免的事情.相反,我要检查的是是否已经建立连接,以及是否没有在GUI表单上以文本形式吐出适当的错误.

However, in the callback method thw exception is thrown.This is what I'm trying to avoid. What I want instead is to check if the connection has been made and if it's not spit the the appropriate error as a text on my GUI form.

我试图检查BeginConnect()的返回值,但是它在调用静态方法之前返回.我尝试重新抛出异常并在建立连接(按钮单击事件)时捕获该异常,但是它不起作用.没有捕获异常.

I tried to check a return value of BeginConnect(), but it returns prior to calling the static method. I tried to re-throw the exception and catch it when I establish the connection (button click event), but it does not work. Exception is not caught.

如何检查是否已建立连接?

How do I check if the connection has been made?

我可能可以将文本控件传递给连接类,并在捕获到异常后将文本设置为错误,但是还有其他方法吗?

I can probably pass my text control to the connection class and set the text to an error when exception has been caught, but is there any other way?

谢谢.

class InternetConnector
{
    public void ConnectToHost()
    {
        IPEndPoint ip = new IPEndPoint(IPAddress.Parse(connector_host), connector_port);
        client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        client.Blocking = true;
        client.BeginConnect(ip, new AsyncCallback(ConnectCallback), client);
    }

    private static void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            Socket sock = (Socket)ar.AsyncState;
            sock.EndConnect(ar);
            connectDone.Set();
            Connected = true;
        }
        catch (Exception e)
        {
            throw (e);
        }
    }
}

public partial class Form1 : Form
{
    private bool isRunning = false;
    private InternetConnector client = new InternetConnector();

    private void startStop_Click(object sender, EventArgs e)
    {
        try
        {
            if (!isRunning || !InternetConnector.Connected)
            {
                if (!InternetConnector.Connected)
                {
                    client.SetAddress(ipAddress.Text);
                    client.SetPort(Convert.ToInt32(connectionport.Text));
                    client.ConnectToHost();
                    status.Text = "Signals Receiver: Connected";
                    status.ForeColor = Color.Green;
                    startStop.Text = "Stop";
                    isRunning = true;
                }
                else
                {
                    startStop.Text = "Start";
                    client.DisconnectFromHost();
                    isRunning = false;
                }
            }
        }
        catch(Exception ex)
        {
            status.Text = "Socket Error: " + ex.Message;
        }
    }
 }

如果我使用"throw(e);"回调catch块中的异常未在Click侦听器中捕获.但是回调中需要try/catch,因为错误的连接会引发异常并且不返回错误.

If I use "throw( e );" in the callback catch block exception is not caught in click listener. But try/catch is required in the callback as faulty connection is throwing exception and not returning error.

推荐答案

由于您使用的是异步BeginConnect,因此回调几乎不会在与单击处理程序相同的线程上发生,因此单击处理程序无法捕获例外.

Because you are using the asynchronous BeginConnect, the callback almost never happens on the same thread as your click handler, so there is no way for your click handler to catch the exception.

如果您需要通过异步回调设置UI元素的状态,通常需要在创建UI的同一线程上执行委托.

If you need to set the status of a UI element from an asynchronous callback, you generally need to execute a delegate on the same thread that the UI was created on.

从Control派生的任何UI元素都有一些方法可以帮助您做到这一点( InvokeRequired BeginInvoke ).我修改了您的示例以帮助说明这一点.

Any UI element deriving from Control has some methods to help you do this (InvokeRequired and BeginInvoke). I've modified your sample to help illustrate this.

基本上,您可以传递一个Action委托,如果该委托在异步Connect回调中发生,则将被调用.然后,此错误处理委托可以根据异步连接回调期间引发的异常来完成所有工作,以设置UI状态.

Basically, you can pass in an Action delegate that will be called with the exception if it occurs in the async Connect callback. This error handling delegate can then do all of the work to set the UI status based on the exception that was thrown during the async connect callback.

因为我们需要传递错误处理委托,所以我们必须创建一个结构(称为ConnectionData)来保存我们需要在异步连接回调中访问的所有状态(套接字和错误处理程序)./p>

Because we need to pass in the error handling delegate, we have to create a structure (Called ConnectionData) to hold the all of the state (the socket and the error handler) we need to access in the async connect callback.

class InternetConnector  
{  
    private struct ConnectionData
    {
        public Action<Exception> ErrorHandler { get; set; }
        public Socket Socket { get; set; }
    }

    public void ConnectToHost(Action<Exception> errorHandler)  
    {  
        IPEndPoint ip = new IPEndPoint(IPAddress.Parse(connector_host), connector_port);  
        client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        var connectionData = new ConnectionData { ErrorHandler = errorHandler, Socket = client };

        client.Blocking = true;  
        client.BeginConnect(ip, new AsyncCallback(ConnectCallback), connectionData);  
    }  

    private static void ConnectCallback(IAsyncResult ar)  
    {  
        ConnectionData connectionData = new ConnectionData();
        try  
        {  
            connectionData = (ConnectionData)ar.AsyncState;  
            connectionData.Socket.EndConnect(ar);  
            connectDone.Set();  
            Connected = true;  
        }  
        catch (Exception e)  
        {  
            if (connectionData.ErrorHandler != null)
                connectionData.ErrorHandler(e);
        }  
    }  
}  

public partial class Form1 : Form       
{       
    private bool isRunning = false;       
    private InternetConnector client = new InternetConnector();       

    private void AsyncErrorHandler(Exception e)
    {
        if (status.InvokeRequired)
        {
            // queue a call to ourself on control's UI thread and immediately return
            status.BeginInvoke(new Action(()=>AsyncErrorHandler(e)));
            return;
        }

        // we are on the right thread to set the status text
        status.Text = "Async Error: " + ex.Message;  
    }

    private void startStop_Click(object sender, EventArgs e)       
    {       
        try       
        {       
            if (!isRunning || !InternetConnector.Connected)       
            {       
                if (!InternetConnector.Connected)       
                {       
                    client.SetAddress(ipAddress.Text);       
                    client.SetPort(Convert.ToInt32(connectionport.Text));       

                    // connect, pass in the method to use for error reporting
                    client.ConnectToHost(AsyncErrorHandler);       

                    status.Text = "Signals Receiver: Connected";       
                    status.ForeColor = Color.Green;       
                    startStop.Text = "Stop";       
                    isRunning = true;       
                }       
                else       
                {       
                    startStop.Text = "Start";       
                    client.DisconnectFromHost();       
                    isRunning = false;       
                }       
            }       
        }       
        catch(Exception ex)       
        {       
            status.Text = "Socket Error: " + ex.Message;       
        }       
    }       
}       

这篇关于如何检查我是否已连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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