2013-06-26 62 views
0

我已經創建了一個wcf服務來測試wcf超時。我的問題是甚至超時已過期其仍然有效。當前線程甚至服務超時?

在此服務中,我創建了長時間運行的方法,並在那裏創建了日誌文件,然後讓服務超時。但即使服務超時也過期了,仍然有日誌文件將數據附加到長時間運行的方法完成執行。 ?

這是怎麼發生的?有沒有辦法阻止?

服務超時1個分鐘

長時間運行的方法,持續時間:10分鐘

該服務在IIS 7.5託管使用WAS

這裏是我的服務實現類

public class LongRunner : ILongRunner 
{ 
    public void LongRunnerMethod() 
    { 
     int counter = int.Parse(ConfigurationManager.AppSettings["val"]); 
     string text = string.Empty; 

     for (int i = 0; true; i++) 
     { 
      Thread.Sleep(1000); 
      if (i >= counter) 
       break; 
      text = string.Concat(i.ToString(), DateTime.Now.ToString()); 
      File.AppendAllText(@"C:\Looger\log.txt", text); 
     } 
    } 
} 

這是我的服務界面王牌

[ServiceContract] 
public interface ILongRunner 
{ 
    [OperationContract] 
    void LongRunnerMethod(); 
} 

最後這裏是web配置

<?xml version="1.0"?> 
    <configuration> 
    <appSettings> 
    <add key="val" value="600"/> 
    </appSettings> 
    <system.web> 
    <compilation debug="true" targetFramework="4.0" /> 
    </system.web> 
    <system.serviceModel> 
    <services> 
     <service behaviorConfiguration="ORServiceBehavior" name="PTS.LongRunner"> 
     <endpoint binding="netTcpBinding" bindingConfiguration="DefaultNetTcpBinding" name="ORServiceTCPEndPoint" 
       contract="PTS.ILongRunner" address="" > 
      <identity> 
      <dns value="localhost" /> 
      </identity> 
     </endpoint> 
     <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange"/> 
     <host> 
      <baseAddresses> 
      <add baseAddress="net.tcp://localhost:8079/___/_________.svc" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    <bindings> 
     <netTcpBinding> 
     <binding name="DefaultNetTcpBinding" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" > 
      <reliableSession enabled="false" ordered="false" inactivityTimeout="00:10:00"/> 
      <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="32" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/> 
      <security mode="Message"> 
      <transport clientCredentialType="Windows"/> 
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="ORServiceBehavior"> 
      <serviceMetadata httpGetEnabled="false" /> 
      <serviceDebug includeExceptionDetailInFaults="false" /> 
      <serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="200" maxConcurrentInstances="200" /> 
      <dataContractSerializer maxItemsInObjectGraph="50000" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 

    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"/> 
    </system.webServer> 

    </configuration> 
+1

我編輯了自己的冠軍。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

+0

[爲什麼WCF不支持服務端超時?](http://stackoverflow.com/questions/4974640/why-doesnt-wcf-support-service-side-timeouts) –

回答

0

WCF有許多超時...

  • 結合超時:的SendTimeout,OpenTimeout和CloseTimeout(默認爲1分鐘)ReceiveTimeout(默認10分鐘)
  • 服務主機:OpenTimeout(默認1分鐘),CloseTimeout(默認10秒)
  • 可靠會話不活動超時:默認10分鐘
  • 任何繼承ConnectionOrientedTransportBindingElement的內容例如NetTcp:ChannelInitializationTimeout默認30秒

我的猜測是,你已經得到了「未處理的異常:System.TimeoutException:公開運行....在規定的超時時間內沒有完成」 - 這意味着,代理具有定時等待服務發送回覆。

「這是如何發生?[即服務不斷記錄,即使你有一個‘操作沒有完成’超時]」

的ServiceHost已分配一個線程來處理對LongRunnerMethod方法提出的要求。此線程將完成處理請求,直到從方法內部引發災難性事件(例如進程主機關閉)或異常。

「有沒有辦法阻止[中斷線程處理方法調用]?」

您需要從外部來源獲取信號,您需要在每次第n次迭代時檢查以確定是否應該繼續。您需要從客戶端以唯一的ID(票證)形式傳遞某些信息到第一個方法,然後使用此ID與一個Cancel方法來設置LongRunnerMethod中止處理的信號。

下面是使用MSMQ,讓真正的單向通話的例子:

服務器

class Program 
    { 
     static void Main(string[] args) 
     { 
      var baseAddress = "net.msmq://localhost/private/"; 
      var address = "ILongRunner"; 

      var host = new ServiceHost(typeof (LongRunner), new Uri(baseAddress)); 
      var binding = new NetMsmqBinding(NetMsmqSecurityMode.None); 
      var se = host.AddServiceEndpoint(typeof (ILongRunner), binding, address); 
      se.VerifyQueue(); //comes from IDesign ServiceModelEx http://www.idesign.net/Downloads/GetDownload/1887 
      host.Open(); 

      Console.WriteLine("Press any key to stop"); 
      Console.ReadLine(); 
     } 
    } 

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)] 
    public class LongRunner : ILongRunner 
    { 
     private static readonly ConcurrentBag<Guid> Cancelations = new ConcurrentBag<Guid>(); 

     public void CancelLongRunnerMethod(Guid id) 
     { 
      if (Cancelations.All(z => z != id)) 
       Cancelations.Add(id); 
     } 

     public void LongRunnerMethod(Guid id) 
     { 
      int counter = 300000; 

      //concurrent write will require different technique 
      var file = string.Format(@"D:\log.{0}.txt", id); 

      for (int i = 0; true; i++) 
      { 
       //check every 5th call 
       if (i % 5 == 0) 
       { 
        if (Cancelations.Any(z => z == id)) 
        { 
         Guid cancelationId; 

         Cancelations.TryTake(out cancelationId); 

         if (cancelationId == id) 
         { 
          Debug.WriteLine(string.Format("LongRunnerMethod {0} canceled", id)); 
          return; 
         } 
        } 
       } 

       Thread.Sleep(10); 
       Console.WriteLine("at " + i); 
       if (i >= counter) 
        break; 
       var text = string.Format("{0} {1} \n", i.ToString(), DateTime.Now.ToString()); 
       File.AppendAllText(file, text); 
      } 

      Console.WriteLine("Complete " + id); 
     } 


    } 

    [ServiceContract()] 
    public interface ILongRunner 
    { 
     [OperationContract(IsOneWay = true)] 
     void CancelLongRunnerMethod(Guid id); 

     [OperationContract(IsOneWay = true)] 
     void LongRunnerMethod(Guid id); 
    } 

CLIENT

class Program 
    { 
     static void Main(string[] args) 
     { 
      var baseAddress = "net.msmq://localhost/private/"; 
      var address = "ILongRunner"; 


      var binding = new NetMsmqBinding(NetMsmqSecurityMode.None); 
      var c1 = new ChannelFactory<ILongRunner>(binding, new EndpointAddress(new Uri(baseAddress + address))); 
      var proxy = c1.CreateChannel(); 
      var request1 = Guid.NewGuid(); 
      proxy.LongRunnerMethod(request1); 
      var co = c1 as ICommunicationObject; 
      co.Close(); 


      var c2 = ChannelFactory<ILongRunner>.CreateChannel(binding, new EndpointAddress(new Uri(baseAddress + address))); 
      var request2 = Guid.NewGuid(); 
      c2.LongRunnerMethod(request2); 

      Thread.Sleep(5000); 
      var c3 = new ChannelFactory<ILongRunner>(binding, new EndpointAddress(new Uri(baseAddress + address))); 
      var proxy2 = c3.CreateChannel(); 
      proxy2.CancelLongRunnerMethod(request1); 
      var co2 = c3 as ICommunicationObject; 
      co2.Close(); 
     } 
    } 
相關問題