मैं एक विंडोज़ ऐप से विंडोज़ सेवा से इंटर-प्रोसेस डब्ल्यूसीएफ संचार करने के लिए netNamedPipeBinding
का उपयोग कर रहा हूं।उपयोग में कॉलबैक के साथ बंद कनेक्शन पर डब्ल्यूसीएफ अपवाद
अब मेरा ऐप अन्य सभी खातों में अच्छी तरह से चल रहा है (डब्ल्यूसीएफ अपवादों के मेरे उचित हिस्से से लड़ने के बाद डब्ल्यूसीएफ के साथ काम करने वाले किसी भी व्यक्ति को पता चलेगा ..) लेकिन यह त्रुटि वह है जो काफी लचीला साबित हो रही है।
मेरे परिदृश्य की एक तस्वीर पेंट करने के लिए: मेरी विंडोज़ सेवा को विंडोज ऐप में दबाए गए बटन के माध्यम से किसी भी समय कुछ काम करने के लिए कतारबद्ध किया जा सकता है और फिर netNamedPipeBinding
पर बात करता है जो कि बाध्यकारी है जो कॉलबैक का समर्थन करता है (दो -वे संचार) यदि आप परिचित नहीं हैं और इस काम को करने का अनुरोध शुरू करते हैं, (इस मामले में एक फ़ाइल अपलोड प्रक्रिया) यह फ़ाइल प्रगति से स्थानांतरित करने के लिए हर कुछ सेकंड कॉलबैक (घटनाओं) को भी गति देता है। विंडोज ऐप के लिए, तो कुछ काफी तंग क्लाइंट-सर्वर एकीकरण है; इस तरह मैं अपने विंडोज़ ऐप में अपनी विंडोज़ सेवा में जो चल रहा है उसकी प्रगति प्राप्त करता हूं।
अब, सभी महान हैं, डब्ल्यूसीएफ देवताओं ने अभी मेरे साथ अपेक्षाकृत खुश हैं, एक बार जब मैं ऐप को समय-समय पर बंद कर देता हूं (जो एक पूरी तरह से मान्य परिदृश्य है)। जबकि एक हस्तांतरण का कार्य प्रगति पर है, और कॉलबैक बहुत भारी फायरिंग कर रहे हैं, मैं इस त्रुटि मिलती है:
System.ServiceModel.ProtocolException:
The channel received an unexpected input message with Action
'http://tempuri.org/ITransferServiceContract/TransferSpeedChangedCallback'
while closing. You should only close your channel when you are not expecting
any more input messages.
अब मैं उस त्रुटि को समझते हैं, लेकिन दुर्भाग्य से मैं कभी नहीं किसी भी अधिक इनपुट messsages प्राप्त करने के बाद अपने चैनल को बंद करने के गारंटी नहीं दे सकते, के रूप में उपयोगकर्ता किसी भी समय ऐप को बंद कर सकता है इसलिए काम अभी भी विंडोज सेवा की पृष्ठभूमि में जारी रहेगा (जैसे वायरस स्कैनर कैसे काम करता है)। उपयोगकर्ता को जीत प्रबंधन टूल ऐप को शुरू और बंद करने में सक्षम होना चाहिए जितना उन्हें हस्तक्षेप नहीं होता है।
अब त्रुटि, मुझे अपना Unsubscribe()
कॉल करने के तुरंत बाद प्राप्त होता है जो ऐप को समाप्त करने से पहले दूसरा अंतिम कॉल है और मुझे विश्वास है कि डब्ल्यूसीएफ क्लाइंट को डिस्कनेक्ट करने का पसंदीदा तरीका क्या है। कनेक्शन को बंद करने से पहले सभी सदस्यता रद्द करने से पहले क्लाइंट आईडी को एक सरणी से हटा दिया जाता है जो स्थानीय रूप से जीत सेवा wcf सेवा पर संग्रहीत किया जाता है (क्योंकि यह एक जीत है जो जीत सेवा और विंडोज ऐप दोनों द्वारा साझा किया जाता है क्योंकि जीत सेवा काम कर सकती है अनुसूचित घटनाएं स्वयं ही) और क्लाइंट आईडी सरणी हटाने के बाद मैं निष्पादित करता हूं, जो मुझे उम्मीद है (महसूस) एक स्वच्छ डिस्कनेक्शन होना चाहिए।
इसका परिणाम, अपवाद प्राप्त करने के अलावा, मेरा ऐप लटकता है, यूआई कुल लॉक अप, प्रगति सलाखों और सब कुछ मध्य मार्ग में है, जिसमें रेस हालत या डब्ल्यूसीएफ डेडलॉक [श्वास] होने के संकेत देने वाले सभी संकेत हैं, लेकिन अब मैं काफी धागा-समझदार हूं और मुझे लगता है कि यह अपेक्षाकृत अलग स्थिति है और अपवाद को पढ़ने के रूप में है, मुझे नहीं लगता कि यह एक 'धागा' मुद्दा है, क्योंकि यह प्रारंभिक डिस्कनेक्शन का एक मुद्दा बताता है फिर मेरे सभी धागे को मेहेम में सर्पिल करता है, शायद ताला लगा देता है।
public void Unsubscribe()
{
try
{
// Close existing connections
if (channel != null &&
channel.State == CommunicationState.Opened)
{
proxy.Unsubscribe();
}
}
catch (Exception)
{
// This is where we receive the 'System.ServiceModel.ProtocolException'.
}
finally
{
Dispose();
}
}
और मेरे Dispose()
विधि है, जो स्वच्छ डिस्कनेक्ट करने होंगे::
public void Dispose()
{
// Dispose object
if (channel != null)
{
try
{
// Close existing connections
Close();
// Attempt dispose object
((IDisposable)channel).Dispose();
}
catch (CommunicationException)
{
channel.Abort();
}
catch (TimeoutException)
{
channel.Abort();
}
catch (Exception)
{
channel.Abort();
throw;
}
}
}
और WCF सेवा Subscription()
समकक्ष और वर्ग
ग्राहक पर मेरे Unsubscribe()
दृष्टिकोण इस तरह दिखता है विंडोज सेवा सर्वर पर गुण (संदर्भ के लिए) (यहां कुछ भी मुश्किल नहीं है और मेरा अपवाद होता है ग्राहक के पक्ष):
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class TransferService : LoggableBase, ITransferServiceContract
{
public void Unsubscribe()
{
if (clients.ContainsKey(clientName))
{
lock (syncObj)
{
clients.Remove(clientName);
}
}
#if DEBUG
Console.WriteLine(" + {0} disconnected.", clientName);
#endif
}
...
}
इंटरफेस की:
[ServiceContract(
CallbackContract = typeof(ITransferServiceCallbackContract),
SessionMode = SessionMode.Required)]
public interface ITransferServiceContract
{
[OperationContract(IsInitiating = true)]
bool Subscribe();
[OperationContract(IsOneWay = true)]
void Unsubscribe();
...
}
कॉलबैक अनुबंध के इंटरफेस है, यह बहुत ही रोमांचक कुछ भी नहीं है, सिर्फ प्रतिनिधियों के माध्यम से घटनाओं आदि कारण मैं इस शामिल दिखाने के लिए है कॉल आप मेरे गुण।
[CallbackBehavior(UseSynchronizationContext = false,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class TransferServiceCallback : ITransferServiceCallbackContract
{ ... }
सच आशा किसी को मेरी मदद कर सकते हैं: मैं पहले से ही UseSynchronizationContext = false
शामिल करके गतिरोध का एक सेट को कम किया! बहुत बहुत धन्यवाद :) :)
मैं विशिष्ट मुद्दे के बारे में पता नहीं है, लेकिन जानकारी के लिए सूत्रण घपला लगता है * संभवतः कारण कैसे WCF सिंक संदर्भ (जो WinForms आदि में फ़ॉर्म है) का उपयोग करता है करने के लिए *। –
धन्यवाद मार्क, हाँ जिसने मुझे पकड़ा और मैंने उस मुद्दे पर पढ़कर डेडलॉक्स के एक सेट को कम किया, चाल को कॉलबैक अनुबंध पर 'UseSynchronizationContext = false' सेट करना था;) मैं इसे अपने उदाहरणों में जोड़ दूंगा। – GONeale
आह, दाएं; यह देखने के लिए अच्छा है कि आप इसे पहले ही कवर कर चुके हैं; पी –