2013-06-26 34 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(); 
     } 
    } 
相关问题