我已经创建了一个wcf服务来测试wcf超时。我的问题是,即使超时,它仍然有效。
在这个服务中我创建了长时间运行的方法,并在那里我创建了日志文件,然后我让服务超时。但即使服务超时已经过期仍然是日志文件附加数据,直到长时间运行的方法完成执行。
这是怎么发生的?有没有办法阻止它?
服务超时为1分钟
长时间运行方法持续时间为:10分钟
此服务使用WAS在IIS 7.5中托管
这是我的服务实现类
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();
}
最后这里是网络配置
<?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>
答案 0 :(得分:0)
WCF有很多超时......
我的猜测是你得到了“未处理的异常:System.TimeoutException:打开的操作没有在分配的超时时间内完成......” - 这意味着代理已经超时等待服务发送响应。
“这是怎么发生的?[即使你的”操作没有完成“,服务也会继续记录”超时“”
ServiceHost已经分配了一个线程来处理对LongRunnerMethod方法的请求。该线程将完成对请求的处理,直到从方法内部引发灾难性(例如进程主机关闭)或异常为止。
“有没有办法停止[中断处理方法调用的线程]?”
您需要从外部源获取您需要在每第n次迭代检查的信号,以确定是否应该继续。您需要以唯一ID(票证)的形式从客户端传递某些内容到第一个方法,然后使用此ID和Cancel方法,该方法将设置LongRunnerMethod的信号以中止处理。
以下是使用msmq的示例,它允许真正的单向调用:
SERVER
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);
}
客户端
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();
}
}