最終的に、WCF デュプレックス Silverlight 4 クライアント404 Not Found
は、ポーリングが WCF サービスから Silverlight クライアントに送信された直後に、ポーリング メッセージのエラーを受け取り始めます。これは、2 回目のポーリングで発生する場合があり、接続が数時間または数日かかることもありますが、ほとんどの場合、最初の数分で失敗します。
! そして興味深いのは、MaxMessagesPerPoll
デュプレックス モードを使用している場合の既知の Silverlight 4 のバグのような問題であり、解決策はこことここで説明されていますが、私はSingleMessagePerPoll
モードを使用しています。とにかくClientStack
、提案どおりに使用してみましたが、何も変わりませんでした。
一般的な流れ:
- SL クライアントが WCF サービス メソッドを実行し、応答を受信
- 次に、すぐにSL クライアントがポーリング メッセージをサービスに送信し始め、2 番目または Ns のポーリング メッセージの例外を取得します。
System.Net.WebException: リモート サーバーがエラーを返しました: NotFound
- Fiddler
404
は、ポーリング メッセージに対して空の応答のみを表示します - その後、クライアント Channel Faulted イベントが発生しました
このような障害が発生した後、SL クライアントを再接続しようとしています。単一の再接続再試行フロー:
Faulted
イベントを処理する- 次のようなすべてのチャンネル イベントの登録を解除します
Closed/Closing/Opened/Opening
- を使用して正しい方法でチャネルを閉じます
try { close } catch { abort }
- 以下のすべては、新しいスレッド ポール スレッドにあります:(私はこれがわずかに安定して動作することを発見しました -この記事を参照してください)
- 45 ~ 70 秒待ちます
- 同じ
DuplexChannelFactory<T>
インスタンスを使用して新しいチャネルを作成し、ログ記録のみを目的としてすべてのチャネル イベントをサブスクライブします。 - WCF サービス メソッドの実行
1 ~ 10 回の再試行 (~1 ~ 10 分) の後、クライアントは最終的にサーバーに接続し、通常のポーリングを続行します。
WCF サービス ログを見ると、すべての cleint リクエストが例外なく処理されていることがわかります。そのため、Silverlight クライアント側で何かが発生しているようです。
一般的な情報:
- .NET フレームワーク 4.0
- PollingDuplex
- 非同期 WCF メソッド
- IIS 6.0 がホストする WCF サービス
- Silverlight 4 クライアント
- クライアント OS: Windows XP SP2
- サーバー OS: Windows 2003 R2 SP2
- NTLM 認証
- DuplexMode: SingleMessagePerPoll
- サービスが機能する前に要求/応答を行う他の WCF サービスがあり、二重接続を使用しません
- SL クライアント サービスでは、すべてを UI に記録しているので、すべてのイベント フローを確認し、特定のイベントごとに時間を取ります。
- IIS ログ、サーバー イベント ログにエラーなし
クライアント:
var binaryBinding = new BinaryMessageEncodingBindingElement();
binaryBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
var httpbindingElement = new HttpTransportBindingElement
{
MaxReceivedMessageSize = 131072
};
var pollingDuplexBindingElement = new PollingDuplexBindingElement
{
ClientPollTimeout = new TimeSpan(0, 0, 1, 30),
InactivityTimeout = new TimeSpan(0, 8, 0, 0),
};
_binding = new CustomBinding(
pollingDuplexBindingElement,
binaryBinding,
httpbindingElement)
{
SendTimeout = new TimeSpan(0, 0, 0, 45),
CloseTimeout = new TimeSpan(0, 0, 0, 25),
ReceiveTimeout = new TimeSpan(0, 8, 0, 0),
OpenTimeout = new TimeSpan(0, 0, 0, 45)
};
httpbindingElement.AuthenticationScheme = AuthenticationSchemes.Negotiate;
var endpoint = new EndpointAddress(_endpointAddress);
_channelFactory = new DuplexChannelFactory<TWebService>(
new InstanceContext(instanceOfClientServiceClass),
_binding,
endpoint);
// then this factory used to create a new channels
// Also for a new channel I'm setting OpTimeout
var contextChannel = newChannel as IContextChannel;
if (contextChannel != null)
{
contextChannel.OperationTimeout = TimeSpan.FromSeconds(45);
}
サーバ:
- WCF、PerSession、マルチスレッド
- すべてがスレッドセーフです
- 実行中のサーバー サービス例外なし
- たくさんのログがあるので、サービスで何が起こっているかがわかります
- すべての WCF トレースは switchValue
All
で有効化されており、疑わしいものはありません
<binding name="customName"
sendTimeout="00:01:00"
receiveTimeout="08:00:00"
openTimeout="00:01:00"
closeTimeout="00:00:35">
<pollingDuplex
inactivityTimeout="08:00:00"
serverPollTimeout="00:01:00" />
<binaryMessageEncoding />
<httpTransport authenticationScheme="Ntlm"
maxReceivedMessageSize="131072">
</httpTransport>
</binding>
<behavior name="customBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling
maxConcurrentCalls = "500"
maxConcurrentSessions = "500"
maxConcurrentInstances = "500" />
</behavior>