Client/Client.cs
author sl
Tue, 16 Dec 2014 13:24:12 +0100
changeset 78 f0dda362f77e
parent 77 042c1fa136b9
child 80 408ef0501cb7
permissions -rw-r--r--
Prevent stackoverflow when client reconnects.
Client now specifies layout rather than relying on default one.
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Windows.Forms;
     7 using SharpDisplay;
     8 using System.ServiceModel;
     9 using System.ServiceModel.Channels;
    10 
    11 
    12 namespace SharpDisplayClient
    13 {
    14     /// <summary>
    15     ///
    16     /// </summary>
    17     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    18     public class Callback : ICallback, IDisposable
    19     {
    20         private MainForm MainForm { get; set; }
    21 
    22         public Callback(MainForm aMainForm)
    23         {
    24             MainForm = aMainForm;
    25         }
    26 
    27         public void OnConnected()
    28         {
    29             //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    30             //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    31 
    32             MessageBox.Show("OnConnected()", "Client");
    33         }
    34 
    35 
    36         public void OnCloseOrder()
    37         {
    38             //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    39             //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    40 
    41             //MessageBox.Show("OnServerClosing()", "Client");
    42             MainForm.CloseConnectionThreadSafe();
    43             MainForm.CloseThreadSafe();
    44         }
    45 
    46         //From IDisposable
    47         public void Dispose()
    48         {
    49 
    50         }
    51     }
    52 
    53 
    54     /// <summary>
    55     ///
    56     /// </summary>
    57     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    58     public class Client : DuplexClientBase<IService>
    59     {
    60         public string SessionId { get { return InnerChannel.SessionId; } }
    61 
    62         public Client(ICallback aCallback)
    63             : base(new InstanceContext(aCallback), new NetTcpBinding(SecurityMode.None, true), new EndpointAddress("net.tcp://localhost:8001/DisplayService"))
    64         { }
    65 
    66         public void SetName(string aClientName)
    67         {
    68             Channel.SetName(aClientName);
    69         }
    70 
    71         public void SetLayout(TableLayout aLayout)
    72         {
    73             Channel.SetLayout(aLayout);
    74         }
    75 
    76         public void SetField(DataField aField)
    77         {
    78             Channel.SetField(aField);
    79         }
    80 
    81         public void SetFields(System.Collections.Generic.IList<DataField> aFields)
    82         {
    83             Channel.SetFields(aFields);
    84         }
    85 
    86         public int ClientCount()
    87         {
    88             return Channel.ClientCount();
    89         }
    90 
    91         public bool IsReady()
    92         {
    93             return State == CommunicationState.Opened || State == CommunicationState.Created;
    94         }
    95     }
    96 
    97 
    98     /// <summary>
    99     /// Handle connection with our Sharp Display Server.
   100     /// If the connection is faulted it will attempt to restart it.
   101     /// </summary>
   102     public class DisplayClient
   103     {
   104         private Client iClient;
   105         private Callback iCallback;
   106         private bool resetingConnection = false;
   107 
   108         private MainForm MainForm { get; set; }
   109         public string SessionId { get { return iClient.SessionId; } }
   110         public string Name { get; private set; }
   111         private TableLayout Layout { get; set; }
   112         private System.Collections.Generic.IList<DataField> Fields { get; set; }
   113 
   114 
   115         public DisplayClient(MainForm aMainForm)
   116         {
   117             MainForm = aMainForm;
   118             Name = "";
   119             Fields = new DataField[]{};
   120         }
   121 
   122         /// <summary>
   123         /// Initialize our server connection.
   124         /// </summary>
   125         public void Open()
   126         {
   127             iCallback = new Callback(MainForm);
   128             iClient = new Client(iCallback);
   129         }
   130 
   131         /// <summary>
   132         /// Terminate our server connection.
   133         /// </summary>
   134         public void Close()
   135         {
   136             iClient.Close();
   137             iClient = null;
   138             iCallback.Dispose();
   139             iCallback = null;
   140         }
   141 
   142         /// <summary>
   143         /// Tells whether a server connection is available.
   144         /// </summary>
   145         /// <returns>True if a server connection is available. False otherwise.</returns>
   146         public bool IsReady()
   147         {
   148             return (iClient != null && iCallback != null && iClient.IsReady());
   149         }
   150 
   151         /// <summary>
   152         /// Check if our server connection is available and attempt reset it if it isn't.
   153         /// This is notably dealing with timed out connections.
   154         /// </summary>
   155         public void CheckConnection()
   156         {
   157             if (!IsReady() && !resetingConnection)
   158             {
   159                 //Try to reconnect
   160                 Open();
   161 
   162                 //Avoid stack overflow in case of persisting failure
   163                 resetingConnection = true;
   164 
   165                 try
   166                 {
   167                     //On reconnect there is a bunch of properties we need to reset
   168                     if (Name != "")
   169                     {
   170                         iClient.SetName(Name);
   171                     }
   172 
   173                     SetLayout(Layout);
   174                     SetFields(Fields);
   175                 }
   176                 finally
   177                 {
   178                     //Make sure our this state does not get out of sync
   179                     resetingConnection = true;
   180                 }
   181             }
   182         }
   183 
   184         public void SetName(string aClientName)
   185         {
   186             Name = aClientName;
   187             CheckConnection();
   188             iClient.SetName(aClientName);
   189         }
   190 
   191 
   192         public void SetLayout(TableLayout aLayout)
   193         {
   194             Layout = aLayout;
   195             CheckConnection();
   196             iClient.SetLayout(aLayout);
   197         }
   198 
   199 
   200         public void SetField(DataField aField)
   201         {
   202             //TODO: Create fields if not present
   203             int i = 0;
   204             foreach (DataField field in Fields)
   205             {
   206                 if (field.Index == aField.Index)
   207                 {
   208                     //Update our field then
   209                     Fields[i] = aField;
   210                     break;
   211                 }
   212                 i++;
   213             }
   214 
   215             CheckConnection();
   216             iClient.SetField(aField);
   217         }
   218 
   219         public void SetFields(System.Collections.Generic.IList<DataField> aFields)
   220         {
   221             Fields = aFields;
   222             CheckConnection();
   223             iClient.SetFields(aFields);
   224         }
   225 
   226 
   227         public int ClientCount()
   228         {
   229             CheckConnection();
   230             return iClient.ClientCount();
   231         }
   232 
   233 
   234 
   235     }
   236 
   237 
   238 }