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.
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.
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?
Thank you.
[EDIT]
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;
}
}
}
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.
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.
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.
Any UI element deriving from Control has some methods to help you do this (
InvokeRequired
andBeginInvoke
). I've modified your sample to help illustrate this.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.
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.
There is property Socket.Connected.
In windows