sta / websocket-sharp

A C# implementation of the WebSocket protocol client and server
http://sta.github.io/websocket-sharp
MIT License
5.71k stars 1.66k forks source link

How to get access to Form objects in WebSocketBehavior class ? #499

Open Shekhrozx opened 6 years ago

Shekhrozx commented 6 years ago

I am using WebSocket server in a Form application. Like below:

public Form1()
        {
            InitializeComponent();

            var wsServer = new WebSocketServer("ws://127.0.0.1");            
            wsServer.AddWebSocketService<WSB>("/rec");
            wsServer.Start();                        
        }

And the WSB:

public class WSB : WebSocketBehavior
        {                         
            protected override void OnOpen()
            {
                //base.OnOpen();
                Console.WriteLine("[Agent INFO]  Connected");                
                IPAddress clientIPAddress = Context.UserEndPoint.Address;               
            }

            protected override void OnMessage(MessageEventArgs e)
            {                
                Console.WriteLine("[Agent INFO]  Message Received");                                
            }                        
        }

And I want to write clientIPAddress to Form1.label.Text. How can I get access to Form1 objects in WSB class' methods ?

segg21 commented 5 years ago

@Shekhrozx maybe you should take a look back at how behaviors work, forms, and property visibility outside of the classes. In the designer, of the form/label you'll see a modifiers property on the label which is set to private. You would set this property to public, along with any other components.

Now for your behavior, you'll need to change it's constructor to accept a reference of this label and or form. As of example,

class WSB : WebSocketBehavior {

    private static System.Windows.Forms.Form form; // you need to store reference of this form to use it

    public WSB(ref System.Windows.Forms.Form _form){
        form = _form;
    }

    protected override void OnOpen(){
        // now, if one of your components of your form is public, for example the label, simply do this
        form.label1.Text = Context.UserEndPoint.Address.ToString();
    }

}

and for initializing this class to pass objects, simply do this

wsServer.AddWebSocketService<WSB>("/rec", ()=> new WSB(ref form));
mikelortega commented 4 years ago

That's great, but using this I get a System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.

It seems WebSocketBehavoiur and the Window work on diferent threads. Do you know how to do it thread safe?

mikelortega commented 4 years ago

Ok, in case somenone finds it useful, I fixed it using:

Application.Current.Dispatcher.Invoke(new Action(() => { /* form code here */ }));

segg21 commented 4 years ago

@mikelortega Right, or you could do

form.Invoke(() => {
    /* form code here */
});