8 Replies - 927 Views - Last Post: 07 October 2011 - 01:39 AM Rate Topic: -----

#1 batesy3k  Icon User is offline

  • D.I.C Regular

Reputation: 41
  • View blog
  • Posts: 299
  • Joined: 10-September 09

Accessing events from an AsyncCallback method

Posted 05 October 2011 - 03:44 AM

Hi :)

Scenario: I am building a client / socket class library to then use in other applications. This library will raise events such as Connected, SendComplete etc. The problem I am having is that my event is always null when using it in a AsyncCallback method - I believe this is to do with it being on a different thread it cannot be seen?

Listen Method
/// <summary>
/// Starts the server listening for connections
/// </summary>
public void Listen()
{
    _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, _localPort); _serverSocket.Bind(ipEndPoint);
    _serverSocket.Listen(_maxPendingConnections);

    // start accepting client connections
    _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);

    // change state to listening
    //_ncState = NetCommStates.Listening;
}


AcceptCallback
/// <summary>
/// Handles the connection request from the client establishing connection with the server (handshake / accepted)
/// </summary>
/// <param name="ar"></param>
private void AcceptCallback(IAsyncResult ar)
{
    // assign client socket meaning connection established with the server
    Socket acceptedClientSocket = _serverSocket.EndAccept(ar);

    // raise OnConnected event
    NetCommConnectedEventArgs e = new NetCommConnectedEventArgs(((IPEndPoint)acceptedClientSocket.RemoteEndPoint).Address.ToString(), ((IPEndPoint)acceptedClientSocket.RemoteEndPoint).Port);
    OnConnected(e);          

    // begin listening for new connections
    _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);

    // add client
    AddClient(acceptedClientSocket);
}


Events / Event Handler
/// <summary>
/// Occurs when connection is achieved (client and server).
/// </summary>
public event EventHandler<NetCommConnectedEventArgs> Connected;

/// <summary>
/// Raises the Connected event.
/// </summary>
private void OnConnected(NetCommConnectedEventArgs e)
{
    EventHandler<NetCommConnectedEventArgs> handler = Connected; // Connected is null - is this because of thread issues? (see attached image)
    if (handler != null)
    {
        handler(null, new NetCommConnectedEventArgs(e.SourceIP, e.SourcePort));
    }
}



Any idea of how to get my OnConnected event to see the event handler correctly?

Any thoughts / points appreciated :)

Attached image(s)

  • Attached Image


Is This A Good Question/Topic? 0
  • +

Replies To: Accessing events from an AsyncCallback method

#2 janne_panne  Icon User is offline

  • WinRT Dev
  • member icon

Reputation: 429
  • View blog
  • Posts: 1,047
  • Joined: 09-June 09

Re: Accessing events from an AsyncCallback method

Posted 05 October 2011 - 04:22 AM

Shouldn't be a thread issue. From the snippets you showed the most obvious problem would be that you aren't listening to the Connected event anywhere. Someone has to listen to the event before it can be raised.
Was This Post Helpful? 0
  • +
  • -

#3 batesy3k  Icon User is offline

  • D.I.C Regular

Reputation: 41
  • View blog
  • Posts: 299
  • Joined: 10-September 09

Re: Accessing events from an AsyncCallback method

Posted 05 October 2011 - 04:30 AM

Here is my client code (a different project which references the class library)
public partial class frmClient : Form
{
    Communicator _client;

    public frmClient()
    {
        InitializeComponent();

        _client = new Communicator();
        _client.Connected += new EventHandler<NetCommConnectedEventArgs>(_client_Connected);
    }

    void _client_Connected(object sender, NetCommConnectedEventArgs e)
    {
        MessageBox.Show("Connected to server " + e.SourceIP);
    }

    private void btnConnect_Click(object sender, EventArgs e)
    {
        _client.Connect();            
    }
}


Can the class library tell that it is being listened to from a different project? Or does something else need to be set-up?

This post has been edited by batesy3k: 05 October 2011 - 04:30 AM

Was This Post Helpful? 0
  • +
  • -

#4 batesy3k  Icon User is offline

  • D.I.C Regular

Reputation: 41
  • View blog
  • Posts: 299
  • Joined: 10-September 09

Re: Accessing events from an AsyncCallback method

Posted 05 October 2011 - 05:12 AM

Update: if I do something like in the class library:
public void DoSomething()
{
    // raise OnConnected event
    NetCommConnectedEventArgs e = new NetCommConnectedEventArgs(((IPEndPoint)acceptedClientSocket.RemoteEndPoint).Address.ToString(), ((IPEndPoint)acceptedClientSocket.RemoteEndPoint).Port);
    OnConnected(e); 
}


and this in my client:
_client.DoSomething();


It then works which made me think originally that it was a thread issue...
Was This Post Helpful? 0
  • +
  • -

#5 lordofduct  Icon User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2533
  • View blog
  • Posts: 4,633
  • Joined: 24-September 10

Re: Accessing events from an AsyncCallback method

Posted 05 October 2011 - 06:56 AM

When is the method 'Listen' called? It appears it's what starts the thread that leads to the firing of the Connected event.

But you don't call it anywhere, you just create a Communicator and attach the handler for said event.

This leads me to believe the Listen() method is being called by the constructor. If this is so it is quite reasonable that the socket connection occurs before you actually add the handler. You should try constructing the Communicator, adding the handler, then calling 'Listen'.

This post has been edited by lordofduct: 05 October 2011 - 06:56 AM

Was This Post Helpful? 0
  • +
  • -

#6 batesy3k  Icon User is offline

  • D.I.C Regular

Reputation: 41
  • View blog
  • Posts: 299
  • Joined: 10-September 09

Re: Accessing events from an AsyncCallback method

Posted 05 October 2011 - 07:24 AM

The Listen method gets called by the server project thus so:
public partial class frmServer : Form
{
    Communicator _server;

    public frmServer()
    {
        InitializeComponent();

        _server = new Communicator();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        _server.Listen();
    }
}


The client then clicks connect in the client project to establish a connection... Does this alter your thinking?
Was This Post Helpful? 0
  • +
  • -

#7 lordofduct  Icon User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2533
  • View blog
  • Posts: 4,633
  • Joined: 24-September 10

Re: Accessing events from an AsyncCallback method

Posted 05 October 2011 - 07:28 AM

so your code keeps morphing each time you post something.

I'm not seeing where the event handler gets attached vs when the actual connection is made.

But if the event is null, I'm betting the event handler hasn't been attached yet. That's usually how that works.





Wait... you call Listen on a Communicator object created in frmServer, and you add a listener to a Communicator object created in frmClient.

Those are two separate objects. The event handlers attached to one can't be accessed from the other.
Was This Post Helpful? 0
  • +
  • -

#8 batesy3k  Icon User is offline

  • D.I.C Regular

Reputation: 41
  • View blog
  • Posts: 299
  • Joined: 10-September 09

Re: Accessing events from an AsyncCallback method

Posted 05 October 2011 - 08:01 AM

Oh yeah I see where you are coming from... So how to achieve what I want to do to alert the client that it has established?

Still don't see why it works when not using the async event handlers but doesn't when I do... any ideas on that? :)
Was This Post Helpful? 0
  • +
  • -

#9 mavarazo  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 36
  • View blog
  • Posts: 182
  • Joined: 25-October 10

Re: Accessing events from an AsyncCallback method

Posted 07 October 2011 - 01:39 AM

I did something similar some times ago:
...
_serverSocket.Listen(4);
_serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
...


private void OnAccept(IAsyncResult ar) {
   try {
      Socket clientSocket = _serverSocket.EndAccept(ar);
      _serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
      clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket);
   }
   catch (Exception ex) {
      AppendMessage(ex.Message, Messages.Exception);
   }
}



private void OnReceive(IAsyncResult ar) {
   try {
      Socket clientSocket = (Socket)ar.AsyncState;
      clientSocket.EndReceive(ar);
   ...
}


This post has been edited by mavarazo: 07 October 2011 - 01:39 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1