私は WCF で NetNamedPipes を使用したことはありませんが、NetTcp のタイムアウト値を学習するのに時間以上の時間を費やしました。私は NetTcpBindings に次の構成を使用しており、接続がアクティブなままで幸運でした。
サーバ:
<binding name="MyBindingName" sendTimeout="00:00:30" receiveTimeout="infinite">
<reliableSession enabled="true" inactivityTimeout="00:05:00" ordered="true" />
<security mode="None" />
</binding>
クライアント:
<binding name="MyBindingName" closeTimeout="00:00:30" openTimeout="00:00:30" receiveTimeout="infinite" sendTimeout="00:00:30">
<reliableSession enabled="true" inactivityTimeout="00:01:00" ordered="true" />
<security mode="None" />
</binding>
私が最も時間を費やした重要な設定は、sendTimeout と receiveTimeout です。receiveTimeout が send と同じかそれ以下の場合、そのタイムアウトに達するとチャネルはドロップします。受信がより高く、送信がしきい値を超えている場合、チャネルはトランスポート レベルのキープアライブを起動します。私のテストでは、sendTimeout のしきい値は 30 秒です。それ未満の場合、キープアライブは送信されません。
さらに、タイマー ベースのキープアライブ コールを毎分実行して、チャネルが正常に動作していることを確認しています。呼び出しは単純にブール値の戻り値のメンバーに対して行われます:
[OperationContract(IsOneWay = false, IsInitiating = false, IsTerminating = false)]
bool KeepAlive();
public bool KeepAlive()
{
return true;
}
また、チャネル イベントを取得して (適切なタイミングで取得した場合)、何か問題が発生した場合に接続を再開することもできます。
InstanceContext site = new InstanceContext(this);
_proxy = new MyServiceChannel(site);
if (_proxy != null)
{
if (_proxy.Login())
{
//Login was successful
//Add channel event handlers so we can determine if something goes wrong
foreach (IChannel a in site.OutgoingChannels)
{
a.Opened += Channel_Opened;
a.Faulted += Channel_Faulted;
a.Closing += Channel_Closing;
a.Closed += Channel_Closed;
}
}
}
これが翻訳され、NetNamedPipes を使用する価値があることを願っています。
編集:サーバーの再起動の問題をキャプチャするためのその他のオプション
サーバーが再起動すると、クライアントのチャネルが閉じられるか、障害が発生します。クライアント側でこれらのイベントをキャプチャすると、サービスが再び利用可能になるまで再接続タイマーを使用するオプションが提供されます。
private void Channel_Faulted(object sender, EventArgs e)
{
IChannel channel = sender as IChannel;
if (channel != null)
{
channel.Abort();
channel.Close();
}
//Disable the keep alive timer now that the channel is faulted
_keepAliveTimer.Stop();
//The proxy channel should no longer be used
AbortProxy();
//Enable the try again timer and attempt to reconnect
_reconnectTimer.Start();
}
private void _reconnectTimer_Tick(object sender, System.EventArgs e)
{
if (_proxy == null)
{
InstanceContext site = new InstanceContext(this);
_proxy = new StateManagerClient(site);
}
if (_proxy != null)
{
if (_proxy.Login())
{
//The connection is back up
_reconnectTimer.Stop();
_keepAliveTimer.Start();
}
else
{
//The channel has likely faulted and the proxy should be destroyed
AbortProxy();
}
}
}
public void AbortProxy()
{
if (_proxy != null)
{
_proxy.Abort();
_proxy.Close();
_proxy = null;
}
}
再接続タイマーのログイン試行がバックグラウンド スレッドで非同期的に行われるようにして、ログインを試行するたびに UI がハングしないようにする必要があります。YMMV