2013-03-04 7 views
5

में शून्य है, मैं डब्ल्यूसीएफ का उपयोग करके एक प्रकाशित/सदस्यता प्रणाली स्थापित करने की कोशिश कर रहा हूं और जहां डब्ल्यूसीएफ सर्वर विंडोज सेवा में है। बाध्यकारी नेट है। टीसीपी। यह सेवा क्लाइंट को "सब्सक्राइब" विधि प्रदान कर रही है ताकि ग्राहक कॉलबैक हैंडलर को ऐसे ईवेंट में पंजीकृत कर सके जो सर्वर से जुड़े डीएलएल से उठाया जाएगा। सदस्यता विधि में मैं OperationContext.Current.GetCallbackChannel विधि का उपयोग कर कॉलबैक चैनल प्राप्त करने का प्रयास करता हूं। जब मैं इसे ऑपरेशन कॉन्टेक्स्ट का प्रयास करता हूं। वर्तमान संपत्ति शून्य लौटाती है।वर्तमान ऑपरेशन कॉन्टेक्स्ट डब्ल्यूसीएफ विंडोज सेवा

क्या कोई मुझे बता सकता है कि यह संपत्ति किस परिस्थिति में वापस आ जाएगी ?? क्या मैंने कुछ स्थापित करना याद किया है? मैं नीचे सेवा कोड और इंटरफेस कोड शामिल होगा। मैं विजुअल स्टूडियो 2012 में सी # का उपयोग कर रहा हूं और फ्रेमवर्क 4.5 को लक्षित कर रहा हूं।

सेवा:

namespace WService 
{ 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
public class WcfPublisherService : IWcfPublisherContract 
{ 
    IOALogic logic = new OAControlExample(); 
    IWcfSubscriberContract _callback = null; 

    public void Subscribe() 
    { 
     _callback = OperationContext.Current.GetCallbackChannel<IWcfSubscriberContract>(); 
     logic.BarriersChanged += logic_BarriersChanged; 
    } 

    public void UnSubscribe() 
    { 
     logic.BarriersChanged -= logic_BarriersChanged; 
    } 

    void logic_BarriersChanged(object sender, BarriersChangedEventArgs e) 
    { 
     _callback.BarriersChanged(e.BarrierLines); 
    } 
} 
} 

इंटरफ़ेस:

namespace WService 
{ 
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IWcfSubscriberContract))] 
public interface IWcfPublisherContract 
{ 
    [OperationContract(IsOneWay=false, IsInitiating=true)] 
    void Subscribe(); 
    [OperationContract(IsOneWay = false, IsTerminating=true)] 
    void UnSubscribe(); 
} 

public interface IWcfSubscriberContract 
{ 
    [OperationContract(IsOneWay = true)] 
    void BarriersChanged(BarrierLines barrierLines); 
} 
} 

ग्राहक:

namespace TestClient 
{ 
public partial class Form1 : Form 
{ 
    WcfPublisherService myService 
     = new WcfPublisherService(); 

    ServiceCallback serviceCallback = new ServiceCallback(); 

    public Form1() 
    { 
     InitializeComponent(); 
     serviceCallback.NewMessage += serviceCallback_NewMessage; 
    } 

    private delegate void serviceCallback_NewMessageDelegate(object sender, NewMessageEventArgs e); 
    void serviceCallback_NewMessage(object sender, NewMessageEventArgs e) 
    { 
     if (textBox1.InvokeRequired) 
     { 
      textBox1.Invoke(new serviceCallback_NewMessageDelegate(serviceCallback_NewMessage), new object[] {sender, e}); 
     } 
     else 
     { 
      if (textBox1.Text.Trim().Length > 1) 
      { 
       textBox1.Text += Environment.NewLine; 
      } 
      textBox1.Text += e.Msg; 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     myService.Subscribe(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     myService.UnSubscribe(); 
    } 
} 

[CallbackBehaviorAttribute(UseSynchronizationContext = false)] 
class ServiceCallback : IWcfSubscriberContract 
{ 
    public delegate void NewMessageEventHandler(object sender, NewMessageEventArgs e); 
    public event NewMessageEventHandler NewMessage; 
    protected virtual void OnNewMessage(string msg) 
    { 
     if (NewMessage != null) 
     { 
      NewMessage(this, new NewMessageEventArgs(msg)); 
     } 
    } 

    public void BarriersChanged(OA.BarrierLines barrierLines) 
    { 
     OnNewMessage("new barrier lines"); 
    } 
} 

public class NewMessageEventArgs : EventArgs 
{ 
    public NewMessageEventArgs(string msg) 
    { 
     this.Msg = msg; 
    } 
    public string Msg { get; set; } 
} 
} 

** * ** * ** * न्यू संपादित * ** * ** * ** * ** * ** SalientBrain के सुझावों के लिए धन्यवाद, मैं अपने प्रोजेक्ट के लिए काफी परिवर्तन किए हैं क्योंकि मुझे एहसास हुआ कि सेवा लंबे समय तक चलनी पड़ी और लगातार चल रही थी, भले ही कोई ग्राहक कनेक्ट न हो, इसलिए मैंने इसे सिंगलटन में बदल दिया। फिर भी, मेरी मूल समस्या अभी भी बनी हुई है। सैलेंटब्रेन ने मेरी कॉन्फ़िगरेशन फ़ाइल देखने के लिए कहा है, इसलिए मैं इसे अन्य सभी प्रासंगिक फ़ाइलों के साथ नीचे शामिल कर दूंगा। मैंने अंतरिक्ष को बचाने के लिए इसे हटा दिया है, लेकिन मुझे नहीं लगता कि मैंने कुछ भी महत्वपूर्ण हटा दिया है। त्रुटि PulisherService कक्षा की सदस्यता विधि में होती है। मुझे आशा है कि यह कुछ बेवकूफ है जो मैंने कॉन्फ़िगरेशन फ़ाइल में किया था। ठीक है, यहाँ यह है:

कॉन्फ़िग:

<configuration> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
    </startup> 
    <system.serviceModel> 
     <behaviors> 
      <serviceBehaviors> 
       <behavior name="WService.WCFPublisherServiceBehavior"> 
        <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" /> 
        <serviceDebug includeExceptionDetailInFaults="false" /> 
       </behavior> 
      </serviceBehaviors> 
     </behaviors> 
     <services> 
      <service behaviorConfiguration="WService.WCFPublisherServiceBehavior" 
       name="WService.WcfPublisherService"> 
       <endpoint address="" binding="netTcpBinding" bindingConfiguration="" 
        name="NetTcpBindingEndpoint" contract="WService.IWcfPublisherContract"> 
        <identity> 
         <dns value="localhost" /> 
        </identity> 
       </endpoint> 
       <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" 
        name="MexTcpBindingEndpoint" contract="IMetadataExchange" /> 
       <host> 
        <baseAddresses> 
         <add baseAddress="net.tcp://localhost:8523/Publisher" /> 
        </baseAddresses> 
       </host> 
      </service> 
     </services> 
    </system.serviceModel> 
</configuration> 

WcfContracts:

namespace WService 
{ 
    [ServiceContract(SessionMode = SessionMode.Allowed, CallbackContract = typeof(IWcfSubscriberContract))] 
    public interface IWcfPublisherContract 
    { 
     [OperationContract(IsOneWay=false)] 
     void Subscribe(string key); 
     [OperationContract(IsOneWay = false)] 
     void UnSubscribe(string key); 
    } 

    public interface IWcfSubscriberContract 
    { 
     [OperationContract(IsOneWay = true)] 
     void BarriersChanged(BarrierLines barrierLines); 
    } 
} 

WcfService:

namespace WService 
{ 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 
    public class WcfPublisherService : IWcfPublisherContract 
    { 
     private static WcfPublisherService _instance = null; 
     private IOALogic _logic = null; 
     private Dictionary<string, IWcfSubscriberContract> _callbacks 
      = new Dictionary<string, IWcfSubscriberContract>(); 
     private ReaderWriterLock _callbacksLock = new ReaderWriterLock(); 

     private WcfPublisherService() { } 

     public static WcfPublisherService TheInstance() 
     { 
      if (_instance == null) 
      { 
       _instance = new WcfPublisherService(); 
      } 
      return _instance; 
     } 

     public void StopWcf() 
     { 
      _logic.StopRequest(); 
     } 

     public void StartWcf(IOALogic logic) 
     { 
      _logic = logic; 
      _logic.BarriersChanged += logic_BarriersChanged; 
      ThreadPool.QueueUserWorkItem(new WaitCallback(StartWork), null); 
     } 

     public void StartWork(object state) 
     { 
      _logic.Run(); 
     } 

     public void Subscribe(string key) 
     { 
      OperationContext context = OperationContext.Current; 
      // The above line returns null *********************************************** 
      _callbacksLock.AcquireWriterLock(2000); 
      if (_callbacksLock.IsWriterLockHeld) 
      { 
       _callbacks.Add(key, context.GetCallbackChannel<IWcfSubscriberContract>()); 
       // The above line throws a null execption because context is null ******** 
       _callbacksLock.ReleaseWriterLock(); 
      } 
     } 

     public void UnSubscribe(string key) 
     { 
      _callbacksLock.AcquireWriterLock(2000); 
      if (_callbacksLock.IsWriterLockHeld) 
      { 
       _callbacks.Remove(key); 
       _callbacksLock.ReleaseWriterLock(); 
      } 
     } 

     void logic_BarriersChanged(object sender, BarriersChangedEventArgs e) 
     { 
      _callbacksLock.AcquireReaderLock(1000); 
      if (_callbacksLock.IsReaderLockHeld) 
      { 
       try 
       { 
        foreach (IWcfSubscriberContract callback in _callbacks.Values) 
        { 
         callback.BarriersChanged(e.BarrierLines); 
        } 
       } 
       finally 
       { 
        _callbacksLock.ReleaseReaderLock(); 
       } 
      } 
     } 
    } 
} 

WindowsService:

namespace WService 
{ 
    public partial class WService : ServiceBase 
    { 
     internal static ServiceHost _serviceHost = null; 
     internal static IOALogic _logic = new OAControlExample(); 

     public WService() 
     { 
      InitializeComponent(); 
     } 

     protected override void OnStart(string[] args) 
     { 
      if (_serviceHost != null) 
      { 
       _serviceHost.Close(); 
      } 

      _serviceHost = new ServiceHost(WcfPublisherService.TheInstance()); 
      WcfPublisherService.TheInstance().StartWcf(_logic); 
      _serviceHost.Open(); 
     } 

     protected override void OnStop() 
     { 
      if (WcfPublisherService.TheInstance() != null) 
      { 
       WcfPublisherService.TheInstance().StopWcf(); 
      } 
      if (_serviceHost != null) 
      { 
       _serviceHost.Close(); 
       _serviceHost = null; 
      } 
     } 
    } 
} 

TestForm:

namespace TestClient 
{ 
    public partial class Form1 : Form 
    { 
     ServiceCallback serviceCallback = new ServiceCallback(); 

     public Form1() 
     { 
      InitializeComponent(); 

      serviceCallback.NewMessage += serviceCallback_NewMessage; 
     } 

     private delegate void serviceCallback_NewMessageDelegate(object sender, NewMessageEventArgs e); 
     void serviceCallback_NewMessage(object sender, NewMessageEventArgs e) 
     { 
      if (textBox1.InvokeRequired) 
      { 
       textBox1.Invoke(new serviceCallback_NewMessageDelegate(serviceCallback_NewMessage), new object[] {sender, e}); 
      } 
      else 
      { 
       if (textBox1.Text.Trim().Length > 1) 
       { 
        textBox1.Text += Environment.NewLine; 
       } 
       textBox1.Text += e.Msg; 
      } 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      serviceCallback.Subscribe(); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      serviceCallback.Unsubscribe(); 
     } 
    } 
} 

TestCallbackClass:

namespace TestClient 
{ 
    [CallbackBehaviorAttribute(UseSynchronizationContext = true)] 
    class ServiceCallback : IWcfSubscriberContract 
    { 
     WcfPublisherService myService 
      = WcfPublisherService.TheInstance(); 
     string callbackKey = Guid.NewGuid().ToString(); 

     public delegate void NewMessageEventHandler(object sender, NewMessageEventArgs e); 
     public event NewMessageEventHandler NewMessage; 
     protected virtual void OnNewMessage(string msg) 
     { 
      if (NewMessage != null) 
      { 
       NewMessage(this, new NewMessageEventArgs(msg)); 
      } 
     } 

     public void Subscribe() 
     { 
      try 
      { 
       myService.Subscribe(callbackKey); 
      } 
      catch (Exception ex) 
      { 
       OnNewMessage("exception: " + ex.Message); 
      } 
     } 

     public void Unsubscribe() 
     { 
      try 
      { 
       myService.UnSubscribe(callbackKey); 
      } 
      catch (Exception ex) 
      { 
       OnNewMessage("exception: " + ex.Message); 
      } 
     } 

     public void BarriersChanged(OAInterface.BarrierLines barrierLines) 
     { 
      OnNewMessage("new barrier lines"); 
     } 
    } 

    public class NewMessageEventArgs : EventArgs 
    { 
     public NewMessageEventArgs(string msg) 
     { 
      this.Msg = msg; 
     } 
     public string Msg { get; set; } 
    } 
} 
+0

आप nettcpbinding का उपयोग कर रहे हैं? – SalientBrain

+0

हाँ मैं nettcpbinding – dtaylor

+2

का उपयोग कर रहा हूं क्या आपने अन्य InstanceContextMode के साथ खेलने का प्रयास किया था? – SalientBrain

उत्तर

17

के रूप में, टिप्पणियों में चर्चा करता है, तो आप सीधे सेवा प्रकार का एक उदाहरण बना सकते हैं - के रूप में एक WCF प्रॉक्सी/clientchannel करने का विरोध किया - और फिर आप कॉल इस पर एक विधि, कोई ऑपरेशन कॉन्टेक्स्ट नहीं है। डब्ल्यूसीएफ एक ऑपरेशन कॉन्टेक्स्ट उदाहरण प्रदान करता है जब आपका ऑपरेशन किसी सेवा के भीतर चल रहा है।

+0

यह सही जवाब था। जब मैंने प्रॉक्सी के उदाहरण के बजाय क्लाइंट में सेवा का एक उदाहरण बनाया, तो मैं अपनी सेवा पर कॉलिंग विधियों पर अपने तरीके से चला गया, यह महसूस नहीं कर रहा था कि यह सेवा का गलत उदाहरण था। केवल एक चीज जिसने मुझे रोक दिया ऑपरेशन कॉन्टेक्स्ट की अनुपस्थिति थी। एक बार फिर धन्यवाद। – dtaylor

4

क्लाइंट कोड में न तो प्रॉक्सी चैनल फैक्ट्री नहीं बनाया गया। सेवा वर्ग उदाहरण कक्षा पुस्तकालय के रूप में बनाया गया है।

आप कोड

ServiceCallback serviceCallback = new ServiceCallback(); 
InstanceContext instanceContext = new InstanceContext(serviceCallback); 

var pubsubProxy = new PubSubProxy.WcfPublisherContractClient(instanceContext); 
pubsubProxy.Subscribe(); 

नीचे के रूप में सेवा का उपभोग और जब सेवा चल रही है, OperationContext बनाई गई है और आप OperationContext.Current

+2

मिलान - आप सही हैं। दुर्भाग्यवश, इयान ने कल प्रश्न की टिप्पणियों में यह पता लगाया था और मैं केवल एक उत्तर को "उत्तर" के रूप में चिह्नित कर सकता हूं। – dtaylor

0

उपयोग कर सकते हैं मैं एक ऐसी ही समस्या हुई चाहिए: मेरे मामले में जब InstanceContextMode को सिंगल द वेबऑपरेशन कॉन्टेक्स्ट पर सेट किया गया था। कंटेंट कन्स्ट्रक्टर में शून्य था। हालांकि यह सेवाओं/कक्षाओं के तरीकों के भीतर उपलब्ध था।

संबंधित मुद्दे