2017-02-17 4 views
1

私は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 

答えて

0

私は私の調査のビットをかなりやりました問題を抱えているすべての開いている接続をループして、タイマーを停止するように指示したため、が含まれています。現在、自分のイベントを呼び出していて、コールバックチャネルにアクセスしようとしていた接続がブロックしました。後

try 
{ 
    con.StopTimer(kvp.Key); 
} 
catch { } 

:あなたが、私は問題を解決するには、以下のコードの変更を実施し、要求

の処理中にコールバックチャネルにアクセスすることはできません

try { if (OperationContext.Current.GetCallbackChannel<ITimeRecordingClient>() != con) { con.StopTimer(kvp.Key); } } catch { } 
関連する問題