私は単純なテストケースのWCFサービスを持っています。考えられるのは、あるプロセスが別のプロセスをコールしてコールバックを登録し、もう1つがイベント発生時に元の呼び出し元を呼び出すということです。 WCFのネイティブコールバックが正しく動作しない、またはこのアプリケーションでは、それを示唆することはありません。私は動作を示す非常に単純なテストプログラムを持っています。 10回の試行ごとに、しばらくの間(一時停止期間)、それ以降の回復が一時停止します。これは、開いている/閉じる/何であれ、チャネルイベントを発生させることなく回復します。私は明らかに何かが欠けする必要があるが、何...WCFは10回の呼び出しごとに黙って威嚇的な方法で失敗します
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Threading;
namespace WCFTest
{
[ServiceContract(Namespace = "http://WCF.WTF")]
public interface IServerEvents
{
[OperationContract(IsOneWay = true)]
void Heartbeat();
}
[ServiceContract(Namespace = "http://WCF.WTF")]
public interface ICallbackEvents
{
[OperationContract(IsOneWay = true)]
void HeartbeatAck();
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
[CallbackBehavior(IncludeExceptionDetailInFaults = true)]
class Program : IServerEvents, ICallbackEvents
{
static AutoResetEvent CalledBack = new AutoResetEvent(false);
static ChannelFactory<IServerEvents> ServerChannelFactory;
static ChannelFactory<ICallbackEvents> ClientChannelFactory;
static ServiceHost ServerHost;
static ServiceHost ClientHost;
static int Timeout = 5;
private Program()
{
}
static void Main(string[] args)
{
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None)
{
OpenTimeout = new TimeSpan(0, 0, Timeout),
SendTimeout = new TimeSpan(0, 0, Timeout),
ReceiveTimeout = new TimeSpan(0, 0, Timeout),
MaxConnections = 50,
ListenBacklog = 50
};
Uri serverUri = new Uri("net.tcp://localhost:3123/WTF");
ServerChannelFactory = new ChannelFactory<IServerEvents>(binding, new EndpointAddress(serverUri));
ClientChannelFactory = new ChannelFactory<ICallbackEvents>(binding, new EndpointAddress("net.tcp://localhost:3123/WTF/Client"));
ServerChannelFactory.Closing += new EventHandler((s,x) => Console.WriteLine("SClosing"));
ServerChannelFactory.Opening += new EventHandler((s, x) => Console.WriteLine("SOpening"));
ServerChannelFactory.Faulted += new EventHandler((s,x)=> Console.WriteLine("SFaulted"));
ClientChannelFactory.Closing += new EventHandler((s, x) => Console.WriteLine("CClosing"));
ClientChannelFactory.Opening += new EventHandler((s, x) => Console.WriteLine("COpening"));
ClientChannelFactory.Faulted += new EventHandler((s, x) => Console.WriteLine("CFaulted"));
ServerHost = StartServer("/Server", new Program(), typeof(IServerEvents));
ClientHost = StartServer("/Client", new Program(), typeof(ICallbackEvents));
while (true)
{
Thread.Sleep(100);
try
{
new Program().Heartbeat();
if (!CalledBack.WaitOne(2500, true))
{
throw new TimeoutException("Epic fail.");
}
}
catch (Exception x)
{
Console.WriteLine("Failed heartbeat.\n{0}", x);
}
}
}
public void Heartbeat()
{
Console.Write(".");
Console.Out.Flush();
try
{
ClientChannelFactory.CreateChannel().HeartbeatAck();
}
catch (Exception x)
{
Console.WriteLine("Couldn't ACK heartbeat.\n{0}", x);
}
}
public void HeartbeatAck()
{
Console.Write("!");
Console.Out.Flush();
CalledBack.Set();
}
private static ServiceHost StartServer<T>(string fragment, T remoteObject, Type interfaceType)
{
ServiceHost retHost = null;
using (AutoResetEvent revent = new AutoResetEvent(false))
{
bool hostOk = false;
// The service host has to be started on a non-sync-context thread or bad things (tm) will happen.
ThreadPool.QueueUserWorkItem((oo) =>
{
try
{
retHost = new ServiceHost(remoteObject, new Uri("net.tcp://localhost:3123/WTF"));
var binding = new NetTcpBinding(SecurityMode.None)
{
OpenTimeout = new TimeSpan(0, 0, Timeout),
SendTimeout = new TimeSpan(0, 0, Timeout),
ReceiveTimeout = new TimeSpan(0, 0, Timeout),
MaxConnections = 50,
ListenBacklog = 50
};
retHost.AddServiceEndpoint(interfaceType, binding, fragment);
retHost.Open();
hostOk = true;
}
catch (Exception xc)
{
Console.WriteLine("Couldn't start WCF Service Host!\n{0}", xc);
}
finally
{
try { revent.Set(); }
catch { }
}
});
revent.WaitOne(5000, true);
return hostOk ? retHost : null;
}
}
}
}
これをすべて読んだ人には別の点があります。 –
ところで、この種のことは、IDisposableを実装しているオブジェクトでDisposeを呼び出さないことを意味します。 –
質問:あなたはなぜあなたのサービスをシングルトンにするのですか?これはちょうどトラブルを必要とします....ベストプラクティスは、通話サービスのアクティベーションを行うことです - プログラムするのがずっと簡単です! –