学习 WCF By Visual Studio 2010 (1)--起步“全双工”

 零起点学吧,以前想学.NET Remoting,我懒人一个到现在也没开始学,这倒好直接WCF吧。 

(一)起步“全双工”(Duplex)

 1 建立一个 服务契约在Visual Studio 中建立一个 “WCF Service Library” 项目 

1.1 建立一个 服务接口 就叫 "ISendMessageService" 吧

 

 1 namespace MessageService
 2 {
 3     [ServiceContract(
 4         Name = "SendMessageService",
 5         Namespace = "SendMessageServiceNameSpace",
 6         SessionMode = SessionMode.Required,
 7         CallbackContract = typeof(IMessageCallback))]
 8     public interface ISendMessageService
 9     {
10         [OperationContract]
11         string SendMessage(string value);
12 
13     }
14 }

 

 

 

 1.2 实现这个接口

 

 1  public class MessageService : ISendMessageService
 2     {
 3         private static List<IMessageCallback> _callbackList = new List<IMessageCallback>();
 4         
 5         #region ISendMessageService Members
 6 
 7         public string SendMessage(string message)
 8         {
 9             IMessageCallback callBack = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
10             
11             if (!_callbackList.Contains(callBack))
12             {
13                 _callbackList.Add(callBack);
14             }
15 
16             _callbackList.ForEach(
17                 delegate(IMessageCallback callback)
18                 { callback.NotifyUI(message); });
19             return string.Format("Send message at{0}:{1}", DateTime.Now, message);
20         }
21         #endregion
22     }

 

 

 

1.3 建立Callback 接口

 

1 //[ServiceContract(CallbackContract=typeof(IMessageCallback))]指明ICallback是一个服务契约了,
2     //所以IMessageCallback不再需要添加ServiceContractAttribute特性。
3     public interface IMessageCallback
4     {
5         //由于服务端不需要回调的返回值,索性将回调操作也设为单向方法。
6         [OperationContract(IsOneWay = true)]
7         void NotifyUI(string message);
8     }

 

 

1.4 服务端配置文件:

 

 1 <?xml version="1.0"?>
 2 <configuration>
 3   <system.serviceModel>
 4     <services>
 5       <service name="MessageService.MessageService">
 6         <endpoint address="Service" binding="wsDualHttpBinding" contract="MessageService.ISendMessageService" name="HttpBinding">
 7           <identity>
 8             <dns value="localhost"/>
 9           </identity>
10         </endpoint>
11         <endpoint address="Service" binding="netTcpBinding" contract="MessageService.ISendMessageService" name="TcpBinding">
12           <identity>
13             <dns value="localhost"/>
14           </identity>
15         </endpoint>
16         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
17         <host>
18           <baseAddresses>
19             <add baseAddress="http://localhost:8732/SendMessage/MessageService/"/>
20             <add baseAddress="net.tcp://localhost:8733/SendMessage/MessageService/"/>
21           </baseAddresses>
22         </host>
23       </service>
24     </services>
25     <behaviors>
26       <serviceBehaviors>
27         <behavior>
28           <serviceMetadata httpGetEnabled="True"/>
29           <serviceDebug includeExceptionDetailInFaults="False"/>
30         </behavior>
31       </serviceBehaviors>
32     </behaviors>
33   </system.serviceModel>
34 </configuration>

 

 

 

2 建立客户端

 2.1 添加 Service References 

 2.2 如果是 通过 Http 实现 Duplex 则还需要修改 App.config 否则在Xp sp2 下回报 80端口已经被占用的异常。

 clientBaseAddress="http://localhost:9999/MyClient

 1 <wsDualHttpBinding>
 2                 <binding name="HttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
 3                     receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
 4                     transactionFlow="false" hostNameComparisonMode="StrongWildcard"
 5                     maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
 6                     messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" clientBaseAddress="http://localhost:9999/MyClient">
 7                     <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
 8                         maxBytesPerRead="4096" maxNameTableCharCount="16384" />
 9                     <reliableSession ordered="true" inactivityTimeout="00:10:00" />
10                     <security mode="Message">
11                         <message clientCredentialType="Windows" negotiateServiceCredential="true"
12                             algorithmSuite="Default" />
13                     </security>
14                 </binding>
15             </wsDualHttpBinding>

 

 

 2.3 客户端建立 Service Reference 实体:

 

1  private void Client_Load(object sender, EventArgs e)
2         {
3             _sendMessageServiceClient = new SendMessageServiceClient(new InstanceContext(this), "TcpBinding");
4             _sendMessageServiceClient.Open();
5         }

 

 

2.4 调用服务端方法。

 

1 private void btn_Send_Click(object sender, EventArgs e)
2         {
3             txt_receive.Text = _sendMessageServiceClient.SendMessage(txt_Message.Text);
4         }

 

 

2.5 实现回调接口 SendMessageServiceCallback

 

1 public partial class Client : Form, SendMessageServiceCallback
2     {
3         private SendMessageServiceClient _sendMessageServiceClient;
4         private SynchronizationContext _uiSyncContext = null;
5 
6         public Client()
7         {
8             InitializeComponent();
9         }

 

 

1 
2 #region SendMessageServiceCallback Members
3 
4         void SendMessageServiceCallback.NotifyUI(string guestName)
5         {
6             txt_Callbacktest.Text = guestName;
7         }
8 
9         #endregion

 

 

大功告成! 这一下就可以在回调的时候更改txt_Callbacktest.Text 属性了。

可是真的这么顺利么?.....

 

问题:TimeOut!! 

 

为什么会 TimeOut?  转自tomore的日志

我们现在来分析是什么导致了TimeoutException的抛出。原因很简单:由于我们对service的调用的是在UI 线程调用的,所以在开始调用到最终得到结果,这个UI Thread会被锁住;但是当service进行了相应的运算的到运算的结果后,需要调用callback对象对client进行回调,默认的情况下,Callback的执行是在UI线程执行的。当Callback试图执行的时候,发现UI 线程被锁,只能等待。这样形成一个死锁,UI线程需要等待CalculateService执行返回后才能解锁,而CalculateService需要Callback执行完成;而Callback需要等到UI线程解锁才能执行。

更多的请参见: 

http://www.winu.cn/space-14160-do-blog-id-25131.html

 

 

—————————————————————————————————————————————————————————————— 

 学习资源:

WCF从理论到实践

http://kb.cnblogs.com/page/43709/

《我的WCF之旅》博文系列汇总

http://www.cnblogs.com/artech/archive/2007/09/15/893838.html 

posted @ 2010-04-27 15:55  刘雨赣  阅读(455)  评论(0编辑  收藏  举报