2009-06-22 10 views
6

मेरे पास एक साधारण डब्ल्यूसीएफ डुप्लेक्स टीसीपी सेवा है जिसे मैं प्रोग्रामेटिक रूप से रोकने की कोशिश कर रहा हूं। अगर मेरे पास कोई कनेक्टेड उपयोगकर्ता नहीं है, तो ServiceHost.Close() बहुत तेज़ है, लेकिन अगर मेरे पास एक कनेक्टेड उपयोगकर्ता भी है, तो मुझे कुछ समय लेने के लिए बंद() फ़ंक्शन मिल जाता है, कभी-कभी> 30 सेकंड्स। क्या यह सामान्य व्यवहार है?WCF ServiceHost.Close() देरी

दूसरी ओर, एबॉर्ट() लगभग तात्कालिक है और इसके बजाय मैं इसका उपयोग करने के लिए प्रेरित हूं।

उत्तर

10

यह हो सकता है। docs राज्य कि

बंद विधि किसी भी अधूरा काम की अनुमति देता है लौटने से पहले पूरा हो जाने की। उदाहरण के लिए, buffered संदेशों को भेजना समाप्त करें।

Close() के लिए एक अधिभार जो एक TimeSpan (और throws यदि समयावधि पार हो गई है) लेता है

Abort() नहीं है देरी के बिना एक WCF मेजबान को रोकने के लिए सबसे अच्छा तरीका है की तरह लग रहा है।

1

यदि आप किसी भी प्रगति सेवा कॉल को मारने के ठीक हैं तो Abort() जाने का रास्ता है। बंद करें() एक सेवा बंद करने का विनम्र तरीका है।

0

मैं क्षमता के लिए बंद() पर abort() के लाभ को देख सकता था, लेकिन मुझे लगता है कि कुछ बुरा हो सकता है। मेरे मामले में, मैं बंद() के लिए प्रतीक्षा करना चाहता हूं ताकि मैं बंदरगाहों का पुन: उपयोग कर सकूं। यह कोड फिर से शुरू होने से पहले सेवाओं को वास्तव में बंद करने की प्रतीक्षा करेगा।

Semaphore cont=new Semaphore(0, 1); 
foreach (ServiceHost s in WCFServices) { 
    try { 
     s.Closed += delegate(Object o, System.EventArgs n) { 
      cont.Release(); 
     }; 
     s.Close(); 
     cont.WaitOne();     
    } catch (Exception) { 
    }//try 
}//for 
+0

मुझे यकीन है कि आप इसे पुनर्व्यवस्थित कर सकते हैं ताकि सभी "एस। क्लोज़()" पहले जारी किए जाएं, और फिर सेमफोर पर प्रतीक्षा करें। –

6

यकीन है कि आप इस तरह से, क्लाइंट-साइड कनेक्शन को बंद कर रहे हैं:

var channel = factory.CreateChannel(); 
var channel.DoSomethingForMe(); 
(channel as ICommunicationObject).Close(); 

आप इस बंद() चैनल पर, बंद() सर्वर प्रतीक्षा करता है पर ऐसा नहीं करते हैं एक बहुत, बहुत लंबा समय, भले ही आप एक छोटा टाइमआउट निर्दिष्ट करते हैं।

+0

यह मेरे लिए काम किया – Pompair

0

मैंने इस समस्या को भी देखा। मेरे कोड मूल रूप से इस तरह दिखाई देता दिखता है:

[TestMethod] 
[Timeout(2000)] 
public void ApiClientTest() 
    { 
     bool ApiSuccessSet, ClientSuccessSet = ApiSuccessSet = false; 
     Api apiService = new ApiTestService(); 
     var clientService = new ClientTestService(); 

     ServiceHost clientHost = new ServiceHost(clientService, new Uri(PipeService)); 
     ServiceHost apiHost = new ServiceHost(apiService, new Uri(PipeService)); 

     //To let us know the services were successfully opened 
     clientHost.Opened += (s, e) => ClientSuccessSet = true; 
     apiHost.Opened += (s, e) => ApiSuccessSet = true; 
     clientHost.AddServiceEndpoint(typeof(IClientService), new NetNamedPipeBinding(), ClientPipeServiceName); 
     apiHost.AddServiceEndpoint(typeof(IApiService), new NetNamedPipeBinding(), ApiPipeServiceName); 
     clientHost.BeginOpen(OnOpen, clientHost); 
     apiHost.BeginOpen(OnOpen, apiHost); 

     //This allows both services to be open for communication. 
     while (!ApiSuccessSet || !ClientSuccessSet) 
      Thread.Yield(); 


     EndpointAddress ApiEndpoint = new EndpointAddress(PipeService + @"/" + ApiPipeServiceName); 
     EndpointAddress clientEndpoint = new EndpointAddress(PipeService + @"/" + ClientPipeServiceName); 

     InstanceContext context = new InstanceContext((IClientCallback)new TestClientCallback()); 
     var ClientChannelFactory = new DuplexChannelFactory<IClientService>(context, new NetNamedPipeBinding(), clientEndpoint); 
     var ApiChannelFactory = new ChannelFactory<IApiService>(new NetNamedPipeBinding(), ApiEndpoint); 
     var ClientChannel = ClientChannelFactory.CreateChannel(); 
     var ApiChannel = ApiChannelFactory.CreateChannel(); 


     clientHost.Close(); 
     apiHost.Close(); 
    } 

void OnOpen(IAsyncResult ar) 
    { 
     ServiceHost service = (ServiceHost)ar.AsyncState; 
     service.EndOpen(ar); 
    } 

मैंने देखा है कि इस कोड को 20 secondsto रन ले लिया। मैं तो इस तरह चैनल कारखानों को बंद करने का फैसला किया:

[TestMethod] 
    [Timeout(2000)] 
    public void ApiClientTest() 
    { 
     bool ApiSuccessSet, ClientSuccessSet = ApiSuccessSet = false; 
     Api apiService = new ApiTestService(); 
     var clientService = new ClientTestService(); 

     ServiceHost clientHost = new ServiceHost(clientService, new Uri(PipeService)); 
     ServiceHost apiHost = new ServiceHost(apiService, new Uri(PipeService)); 

     //To let us know the services were successfully opened 
     clientHost.Opened += (s, e) => ClientSuccessSet = true; 
     apiHost.Opened += (s, e) => ApiSuccessSet = true; 
     clientHost.AddServiceEndpoint(typeof(IClientService), new NetNamedPipeBinding(), ClientPipeServiceName); 
     apiHost.AddServiceEndpoint(typeof(IApiService), new NetNamedPipeBinding(), ApiPipeServiceName); 
     clientHost.BeginOpen(OnOpen, clientHost); 
     apiHost.BeginOpen(OnOpen, apiHost); 


     //This allows both services to be open for communication. 
     while (!ApiSuccessSet || !ClientSuccessSet) 
      Thread.Yield(); 


     EndpointAddress ApiEndpoint = new EndpointAddress(PipeService + @"/" + ApiPipeServiceName); 
     EndpointAddress clientEndpoint = new EndpointAddress(PipeService + @"/" + ClientPipeServiceName); 

     InstanceContext context = new InstanceContext((IClientCallback)new TestClientCallback()); 
     var ClientChannelFactory = new DuplexChannelFactory<IClientService>(context, new NetNamedPipeBinding(), clientEndpoint); 
     var ApiChannelFactory = new ChannelFactory<IApiService>(new NetNamedPipeBinding(), ApiEndpoint); 
     var ClientChannel = ClientChannelFactory.CreateChannel(); 
     var ApiChannel = ApiChannelFactory.CreateChannel(); 


     ClientChannelFactory.Close(); 
     ApiChannelFactory.Close(); 
     clientHost.Close(); 
     apiHost.Close(); 
    } 

इस ओर जाता है मुझे विश्वास है कि लंबे समय लेता है ग्राहक के उदाहरण संदर्भ निपटान किया जाता है।

मुझे संदेह है कि इस समाधान को बेहतर तरीके से संभालने के 3 तरीके हैं।

पहला क्लाइंट पर एक फ़ंक्शन बनाना है जो सत्र समाप्त करने का प्रबंधन करता है। इस तरह से आप सेवा बंद करने से पहले उस विधि को कॉल कर सकते हैं और यह बंद समय को तेज कर देगा।

दूसरा दूसरा असीमित रूप से बंद करना है और कनेक्शन बंद होने पर अन्य प्रसंस्करण करना है।

तीसरा कनेक्शन क्लाइंट को बंद करने के लिए क्लाइंट में प्रोग्राम करना है (विशेष रूप से यदि आप क्लाइंट और सेवा दोनों को नियंत्रित करते हैं) ताकि क्लाइंट सत्र को समाप्त कर सके और सेवा शानदार और जल्दी बंद हो सकती है।