When using WCF, there are four host methods used to start the service: console, winform, IIS, and Windows service. While winform acts as the host, it usually has its own UI display and operations in addition to acting as the host for some business needs. When doing this kind of application, it is often found that calling WCF will cause UI blocking, making winform on the server unable to operate normally.
The following is an example: Server UI1 sDisplays a system time data.5SCall the WCF Service to obtain and display the time data.
Look at the Code:
1. In WCF, service instances use single, getdata to simulate complex operations, with a latency of 5 s.
[Servicecontract] <br/> Public interface iservice1 <br/> {<br/> [operationcontract] <br/> string getdata (); <br/>}</P> <p> [servicebehavior (instancecontextmode = instancecontextmode. single)] <br/> public class service1: iservice1 <br/> {<br/> Public String getdata () <br/>{< br/> // simulate complex operations with a latency of 5 MB <br/> thread. sleep (5000); <br/> return datetime. now. tostring ("HH: mm: SS fff"); <br/>}< br/>}
2. server and client code. (For ease, the server and client use a winform Application)
(1) server (_ host is a reference of servicehost)
Private void setsever () <br/>{< br/> _ host = new servicehost (typeof (wcfwinformhostlib. service1); <br/> _ host. open (); <br/> text + = "[server]"; <br/> timer1.interval = 1000; <br/> timer1.tick + = (S, E) ==>< br/>{< br/> var DATA = datetime. now. tostring ("server: hh: mm: Ss. fff ") + environment. newline; <br/> textbox1.text = Data + textbox1.text; <br/>}; <br/>}
(2) client (_ client directly uses the data contract to obtain remote object reference through channelfactory)
Private void setclient () <br/>{< br/> var factory = new channelfactory <wcfwinformhostlib. iservice1> (<br/> New nettcpbinding (), <br/> "net. TCP: // localhost: 20001/wcfwinformhostlib/service1 "); <br/> _ client = factory. createchannel (); <br/> text + = "[client]"; <br/> timer1.interval = 5000; <br/> timer1.tick + = (S, E) ==>< br/>{< br/> var DATA = "client:" + _ client. getdata () + environment. newline; <br/> textbox1.text = Data + textbox1.text; <br/>}; <br/>}
OK. Run it now to check the actual running status:
1. Start the server. At this time, the data is still normal, and a data record is displayed every 1 s.
2. Start the client, which is also a normal data record every 5s.
Let's look at the server. At this time, the data is no longer normal, and it is changed to 5s with the client. In addition, the drag-and-drop interface on the server also feels very stuck, and the UI is obviously blocked.
Start to find the cause. At first glance, you may find that it is a problem with instancecontextmode = single of the service. It turns out that even if it is changed to percall, it will not change, will the re-import mode be set incorrectly? No. The UI of the application on the concurrencymode. Multiple server is still blocked. After many debugging, it is found that the main cause of this UI blocking is servicehost. It is assumed that some listener operations started by servicehost will conflict with the message loop of the UI. (If you know the specific reason, please leave a message. Thank you ). Let's modify servicehost and throw it into a thread:
Add a threadservicehost class
Public class threadservicehost <br/>{< br/> const int sleeptime = 100; <br/> private servicehost _ servicehost = NULL; <br/> private thread _ thread; <br/> private bool _ isrunning; <br/> Public threadservicehost (type servicetype) <br/>{< br/> _ servicehost = new servicehost (servicetype ); <br/> _ thread = new thread (runservice); <br/> _ thread. start (); <br/>}< br/> void runservice () <br/>{< br/> try <B R/>{< br/> _ isrunning = true; <br/> _ servicehost. open (); <br/> while (_ isrunning) <br/>{< br/> thread. sleep (sleeptime); <br/>}< br/> _ servicehost. close (); <br/> (idisposable) _ servicehost ). dispose (); <br/>}< br/> catch (exception) <br/>{< br/> If (_ servicehost! = NULL) <br/> _ servicehost. close (); <br/>}< br/> Public void stop () <br/>{< br/> lock (this) <br/>{< br/> _ isrunning = false; <br/>}< br/>}
Modify the startup code of the server:
_ Host = newThreadservicehost(Typeof (wcfwinformhostlib. service1 ));
Start the server and client again, and the operation is normal.
Server: one piece of data per 1 s, client: one piece of data per 5S.