介入なしで数日または数週間実行できる WCF クライアント サーバー アプリケーションを作成しようとしています。
クライアントがサーバーとのやり取りを処理する方法は次のとおりです。
static object myLock=new object();
static MyService.IMyService myService;
static void PerformServerInteraction(ref MyService.IMyService myService, Action<MyService.IMyService> action)
{
for (int i = 0; i < 10; i++)
{
lock (myLock)
{
try
{
action(myService);
break;
}
catch (Exception e)
{
LogException(e);
}
myService = new MyServiceClient();
}
Thread.Sleep(5000);
}
}
PerformServerInteraction
クライアント アプリによって複数のスレッドから呼び出されます。
ほとんどの場合、サーバーは正常に動作しているようです (ログにエラーは表示されません)。
クライアントから呼び出されたときのサーバー操作には、数ミリ秒のトップがかかります。
数時間、アプリは問題なく動作します。しかしその後、クライアントの呼び出しは大量にタイムアウトを開始します。
System.TimeoutException: The open operation did not complete within the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The socket transfer timed out after 00:01:00. You have exceeded the timeou
t set on your binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected
host has failed to respond
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
at System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
at System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper)
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.DuplexConnectionPoolHelper.AcceptPooledConnection(IConnection connection, TimeoutHelper& timeoutHelper)
at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at .....my code
クライアント アプリケーションまたはサーバー アプリケーションを再起動するまで、問題は解決しません。複数のクライアント アプリケーションを実行すると、クライアントの 1 つでこの種の問題が他のクライアントに干渉します。
サーバーの起動コードは次のとおりです。
try
{
ThreadPool.SetMaxThreads(int.MaxValue, int.MaxValue);
//lets make sure that BW2 does not disturb the other software on the computer
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal;
//load the shedluer static constructor
ServiceHost svh = new ServiceHost(typeof(MyService));
var tcpbinding = new NetTcpBinding(SecurityMode.None);
//remove limits on the max array size
tcpbinding.MaxBufferPoolSize = 2147483647;
tcpbinding.MaxBufferSize = 2147483647;
tcpbinding.MaxReceivedMessageSize = 2147483647;
tcpbinding.ReaderQuotas.MaxArrayLength = 2147483647;
tcpbinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
tcpbinding.ReaderQuotas.MaxStringContentLength = 2147483647;
tcpbinding.ReaderQuotas.MaxDepth = 2147483647;
if (IsWindowsServer())
{
tcpbinding.MaxConnections = int.MaxValue;
}
var location = "net.tcp://localhost:12345";
svh.AddServiceEndpoint(typeof(IMyService), tcpbinding, location);
// Check to see if the service host already has a ServiceMetadataBehavior
if (!IsWindowsServer())
{
ServiceMetadataBehavior smb = svh.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
//smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
svh.Description.Behaviors.Add(smb);
// Add MEX endpoint
svh.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexTcpBinding(),
location + "/mex"
);
}
svh.Open();
Console.WriteLine("Service maunted at {0}", location);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
svh.Close();
Console.WriteLine("Done");
}
catch (Exception e)
{
Console.WriteLine("Exception");
Console.WriteLine(e);
}
なぜこれが発生するのですか?また、今後これを回避するにはどうすればよいですか?