學會WCF之試錯法——超時
服務契約
[ServiceContract] public interface IService { [OperationContract] string GetData(int value); [OperationContract] string GetString(string value); [OperationContract] void Upload(Request request); } [MessageContract] public class Request { [MessageHeader(MustUnderstand = true)] public string FileName { get; set; } [MessageBodyMember(Order = 1)] public Stream Content {get;set;} }
服務
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)] public class Service : IService { public string GetData(int value) { //Thread.Sleep(120000); return string.Format("You entered: {0}", value); } public string GetString(string value) { //Thread.Sleep(120000); return string.Format("You entered: {0}", value); } public void Upload(Request request) { try { StreamReader sr = new StreamReader(request.Content, Encoding.GetEncoding("GB2312")); StreamWriter sw = new StreamWriter("E:\" + request.FileName + ".txt", false, Encoding.GetEncoding("GB2312")); while (!sr.EndOfStream) { sw.WriteLine(sr.ReadLine()); //Thread.Sleep(5000); } sr.Close(); sw.Close(); } catch (Exception ex) { } } }
服務配置
<system.serviceModel> <services> <service name="WCF_Find_Error_Lib.Service"> <endpoint address="" binding="basicHttpBinding" contract="WCF_Find_Error_Lib.IService"> <identity> <dns value="localhost" /> </identity> </endpoint> <host> <baseAddresses> <add baseAddress="http://localhost/S" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
客戶端代理
public class ServiceProxy
{
public string GetData(int value)
{
string ret = null;
ServiceClient client = null;
try
{
client = new ServiceClient();
ret = client.GetData(value);
client.Close();
}
catch
{
if (client != null)
{
client.Abort();
}
throw;
}
return ret;
}
public string GetString(string value)
{
string ret = null;
ServiceClient client = null;
try
{
client = new ServiceClient();
ret = client.GetString(value);
client.Close();
}
catch
{
if (client != null)
{
client.Abort();
}
throw;
}
return ret;
}
public void Upload(Request request)
{
ServiceClient client = null;
try
{
client = new ServiceClient();
client.Upload(request);
client.Close();
}
catch
{
if (client != null)
{
client.Abort();
}
throw;
}
}
}
[ServiceContractAttribute(ConfigurationName = "IService")]
public interface IService
{
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/GetData", ReplyAction = "http://tempuri.org/IService/GetDataResponse")]
string GetData(int value);
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/GetString", ReplyAction = "http://tempuri.org/IService/GetStringResponse")]
string GetString(string value);
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/Upload", ReplyAction = "http://tempuri.org/IService/UploadResponse")]
void Upload(Request request);
}
[MessageContract]
public class Request
{
[MessageHeader(MustUnderstand = true)]
public string FileName { get; set; }
[MessageBodyMember(Order = 1)]
public Stream Content { get; set; }
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class ServiceClient : System.ServiceModel.ClientBase<IService>, IService
{
public ServiceClient()
{
}
public string GetData(int value)
{
return base.Channel.GetData(value);
}
public string GetString(string value)
{
return base.Channel.GetString(value);
}
public void Upload(Request request)
{
base.Channel.Upload(request);
}
}
客戶端配置
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/S" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService" contract="IService"
name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
1 客戶端呼叫超時
執行客戶端,執行呼叫
ServiceProxy proxy = new ServiceProxy();
string s = proxy.GetData(1);
通過配置sendTimeout引數設定超時時間,超時時間預設為1分鐘,上述配置中採用了預設超時時間。
Message
請求通道在等待 00:00:59.9469970 以後答覆時超時。增加傳遞給請求呼叫的超時值,或者增加繫結上的 SendTimeout 值。分配給此操作的時間可能已經是更長超時的一部分。
Stacktrace:
Server stack trace:
在 System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
在 System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
在 System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
在 System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
在 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
在 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
在 Client.IService.GetData(Int32 value)
在 Client.ServiceClient.GetData(Int32 value) 位置 e:projgxz_myselfWCF_Find_ErrorClientServiceProxy.cs:行號 52
在 Client.ServiceProxy.GetData(Int32 value) 位置 e:projgxz_myselfWCF_Find_ErrorClientServiceProxy.cs:行號 19
在 Client.Program.Main(String[] args) 位置 e:projgxz_myselfWCF_Find_ErrorClientProgram.cs:行號 17
增大客戶端呼叫超時時間,可解決超時問題
例如,超時時間設定為10分鐘,滿足此次呼叫需求。
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" sendTimeout="00:10:00"/>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/S" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService" contract="IService"
name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
2 非活動狀態的最大時間間隔
通過配置receiveTimeout設定時間間隔,預設值為 10 分鐘。
服務例項化模式改為為會話模式:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Reentrant)]
服務端配置
<netTcpBinding>
<binding name="NetTcpBinding_IService" maxBufferSize="270000" maxReceivedMessageSize="270000" transferMode="Buffered" receiveTimeout="00:00:10">
<readerQuotas maxStringContentLength="240000"/>
<reliableSession enabled="true" inactivityTimeout="00:00:10"/>
</binding>
</netTcpBinding>
客戶端配置
<netTcpBinding>
<binding name="NetTcpBinding_IService" sendTimeout="00:00:10" maxBufferSize="2700000" maxReceivedMessageSize="2700000" transferMode="Buffered" >
<readerQuotas maxStringContentLength="240000"/>
</binding>
</netTcpBinding>
客戶端呼叫
using (ServiceClient client = new ServiceClient())
{
StreamReader sr = new StreamReader("D:\CSBMTEMP.txt", Encoding.Default);
string str = sr.ReadToEnd();
sr.Close();
client.GetString(str);
Thread.Sleep(100000);
client.GetString(str);
}
執行客戶端程式,成功捕獲異常
上述異常中給出的錯誤資訊並未指出具體的異常原因,所以從中很難推測是由於超時時間設定問題。遇到此類問題只能根據經驗逐項排查,當然這是很浪費時間的,尤其是對於複雜的程式,更是如此。
-----------------------------------------------------------------------------------------
時間倉促,水平有限,如有不當之處,歡迎指正。