私はWCFを非常に新しくしており、現時点でビジネス要件を稼働させようとしています。あなたにいくつかの背景を与えるために、.NET製品上で他のプロセス(プロセス間通信)と話すことができるWindowsサービスが必要です。このアイデアは、すべての製品で一度に1つのタイマーしか実行できないということです。中央のブローカーは、ユーザーがどちらを実行するかに基づいて各プログラムに開始/停止を指示します。コールバックチャネルを使用するWCF TimeoutException
現在のところ、これを数百の他のプロジェクトに拡張する前に、同じクライアントプロジェクトを2回実行して互いのタイマーを開始/停止させたいだけです。
私は取得していますエラーは、2番目のクライアントがアップ接続し、StartTimerを呼び出したときに発生する、それ以下である:
An unhandled exception of type 'System.TimeoutException' occurred in mscorlib.dll
Additional information: This request operation sent to net.tcp://localhost:9044/TimeRecordingService did not receive a reply within the configured timeout (00:01:00). The time allotted to this operation may have been a portion of a longer timeout. This may be because the service is still processing the operation or because the service was unable to send a reply message. Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.
私が最初に問題が同時接続/最大許容接続に関連するだろうと思いました。しかし、私のApp.Configで以下の設定をしても、問題はまだ発生していることがわかりました。 - WCFサービスとクライアントコールバックを格納するためのインターフェース
インタフェース:
<connectionManagement>
<add maxconnection="500" address="*"/>
</connectionManagement>
...
<serviceBehaviors>
<behavior name="ThrottlingIssue">
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
</behavior>
</serviceBehaviors>
うまくいけば、次のコードは、私は次のプロジェクト構造を持って使用
のものであろう。 (C#)
サービス - WCFサービスを実装し、Windowsサービス(C#)として展開するコードを含む
クライアント - WCFサービスを消費し、コールバックを処理して新しいインスタンスが開かれたときにタイマーを一時停止する)
インタフェース
コールバックインタフェース:
public interface ITimeRecordingClient
{
[OperationContract(IsOneWay = true)]
void ReceiveMessage(string userName, string message);
[OperationContract(IsOneWay = true)]
void StopTimer(string ID);
}
サービスインタフェース:
[ServiceContract(CallbackContract = typeof(ITimeRecordingClient))]
public interface ITimeRecordingService
{
[OperationContract]
void Login(string Username, string Password);
[OperationContract]
void Listen();
[OperationContract]
void StopListening();
[OperationContract]
void StartTimer(string ID);
[OperationContract]
void AddTimer(string ID);
}
サービス:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
public class TimeRecordingServiceImpl : ITimeRecordingService
{
private ApplicationUser _user;
private List<ITimeRecordingClient> _lstCons = new List<ITimeRecordingClient>();
private Dictionary<string, bool> _tmrs = new Dictionary<string, bool>();
public TimeRecordingServiceImpl()
{
System.Net.ServicePointManager.DefaultConnectionLimit = 200;
}
public void Login(string Username, string Password)
{
var user = new ApplicationUser { Username = Username, Password = Password };
_user = user;
foreach (ITimeRecordingClient con in _lstCons)
con.ReceiveMessage(Username, Password);
}
public void AddTimer(string ID)
{
_tmrs.Add(ID, false);
}
public void StartTimer(string ID)
{
List<string> lstIDs = new List<string>();
foreach (KeyValuePair<string, bool> kvp in _tmrs)
{
if (kvp.Key != ID)
{
foreach (ITimeRecordingClient con in _lstCons)
{
try
{
con.StopTimer(kvp.Key);
}
catch { }
}
lstIDs.Add(kvp.Key);
}
}
_tmrs[ID] = true;
foreach (string strID in lstIDs)
_tmrs[strID] = false;
}
public void Listen()
{
var connection = OperationContext.Current.GetCallbackChannel<ITimeRecordingClient>();
_lstCons.Add(connection);
}
public void StopListening()
{
var con = OperationContext.Current.GetCallbackChannel<ITimeRecordingClient>();
_lstCons.Remove(con);
}
}
クライアント
メインフォーム:
Public Class Form1
Private _channelFactory As DuplexChannelFactory(Of ITimeRecordingService)
Private _server As ITimeRecordingService
Private _strID As String
Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
_server.StopListening()
_channelFactory.Close()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim contract = ContractDescription.GetContract(GetType(ITimeRecordingService))
Dim Binding = New NetTcpBinding() With {.TransferMode = TransferMode.Buffered}
Dim EndpointAddress = New EndpointAddress("net.tcp://localhost:9044/TimeRecordingService")
Dim endPoint = New ServiceEndpoint(contract, Binding, EndpointAddress)
Dim clientImpl As New TimeRecordingClientImpl()
AddHandler clientImpl.MessageReceived, AddressOf ShowAlert
AddHandler clientImpl.RequestStopTimer, AddressOf StopTimer
System.Net.ServicePointManager.DefaultConnectionLimit = 200
_channelFactory = New DuplexChannelFactory(Of ITimeRecordingService)(clientImpl, endPoint)
_server = _channelFactory.CreateChannel()
_strID = Guid.NewGuid.ToString()
_server.Listen()
_server.AddTimer(_strID)
_server.StartTimer(_strID)
SlsTimer1.ResetClock()
End Sub
Private Sub StopTimer(ByVal ID As String)
If _strID = ID Then SlsTimer1.StopClock()
End Sub
Private Sub ShowAlert(Title As String, Body As String)
Dim info As New DevExpress.XtraBars.Alerter.AlertInfo(Title, Body)
AlertControl1.Show(Me, info)
End Sub
Private Sub SimpleButton1_Click(sender As Object, e As EventArgs) Handles SimpleButton1.Click
_server.StartTimer(_strID)
SlsTimer1.StartClock()
End Sub
End Class
コールバックの実装:
Public Class TimeRecordingClientImpl
Implements ITimeRecordingClient
Public Event MessageReceived(Username As String, Password As String)
Public Event RequestStopTimer(ID As String)
Public Sub ReceiveMessage(Username As String, Password As String) Implements ITimeRecordingClient.ReceiveMessage
RaiseEvent MessageReceived(Username, Password)
End Sub
Public Sub StopTimer(ID As String) Implements ITimeRecordingClient.StopTimer
RaiseEvent RequestStopTimer(ID)
End Sub
End Class