Implementation features:
The background thread changes the state of the form control (FLOWLAYOUTPANEL1).
with this.flowLayoutPanel1.InvokeRequired = = False, you can know whether the main thread is calling its own control, or whether it is called by other threads.
Use the DisplayDelegate proxy if other threads are called.
When the form is initially initialized, it is allowed to be called between threads:
Checkforillegalcrossthreadcalls = false;
When the form is loaded, an anonymous thread threadstatus is started, and the clientlist list is monitored cyclically. If the value in the list changes, the state of the form control is changed.
namespacexxxx{ Public Partial classFrm_manage:form {//Client Status listdictionary<string, socketclientinfo>clientlist; //calling proxies between threads Private Delegate voidDisplayDelegate (stringClientIP,stringClientnum,stringstatus); //Heart jumper Thread PublicThread Threadstatus {Set;Get; } PublicFrm_manage () {//allow calls between threadsCheckforillegalcrossthreadcalls =false; InitializeComponent (); } Private voidFrm_manage_load (Objectsender, EventArgs e) {Socketserver Socketservice=socketserver.getinstance (); Clientlist=socketservice.getclientdictionary (); Threadstatus=NewThread (() = { while(true) { foreach(Socketclientinfo Iteminchclientlist.values) {BOOLEXISTFLG =false; foreach(Control Subpaninch This. Flowlayoutpanel1.controls) { if(Subpan.name = =item.clientip) {//The terminal is present, changing the display stateSubpan.backcolor =GetBackColor (item.clientstatus); EXISTFLG=true; Break; } } if(!EXISTFLG) { //The terminal does not exist, adding a new controlAdddisplay (Item.clientip, Item.clientnum, item.clientstatus); } } This. Flowlayoutpanel1.refresh (); Thread.Sleep ( +* time);//1-second interval refresh page } }); Threadstatus.start (); } PrivateColor GetBackColor (stringstatus) { if(Status = ="0") { returnColor.silver;//Grey } Else if(Status = ="1") { returnColor.lawngreen;//Green } Else if(Status = ="2") { returnColor.gold;//Yellow } Else if(Status = ="3") { returnColor.orange;//Orange } Else if(Status = ="4") { returncolor.red;//Red } Else { returnColor.silver;//Grey } } Private voidAdddisplay (stringClientIP,stringClientnum,stringstatus) { Try { //if the thread and control that called the function are flowLayoutPanel1 on the same line range if( This. flowlayoutpanel1.invokerequired = =false) { //add content directly to a control on a formPanel pal =NewPanel (); Pal. Name=ClientIP; Pal. Width=disstatusw_px; Pal. Height=disstatush_px; Pal. BackColor=GetBackColor (status); Pal. Controls.Add (pic); This. FLOWLAYOUTPANEL1.CONTROLS.ADD (PAL); } //if the thread that called the function and the control FlowLayoutPanel1 are not on the same thread Else { //by using the Invoke method, let the child thread tell the form thread to complete the corresponding control actionDisplayDelegate disp =Newdisplaydelegate (Adddisplay); //use the Invoke method of the control FlowLayoutPanel1 to execute the display proxy (its type is displaydelegate) This. Flowlayoutpanel1.invoke (disp, ClientIP, clientnum, status); } } Catch(Exception e) {loghelper.writeerror (typeof(Frm_manage), E); } } }}
C # uses proxies for inter-thread invocation