GUI/SharpDisplayClient.cs
author StephaneLenclud
Thu, 01 Jan 2015 23:35:49 +0100
branchMiniDisplay
changeset 447 af40a92d480d
parent 446 0cb7b9f6a6f8
permissions -rw-r--r--
SharpDisplay: Migrating to new robust client scheme.
     1 
     2 using System;
     3 using System.Collections.Generic;
     4 using System.Linq;
     5 using System.Text;
     6 using System.Threading.Tasks;
     7 using System.Windows.Forms;
     8 using SharpDisplay;
     9 using System.ServiceModel;
    10 using System.ServiceModel.Channels;
    11 
    12 
    13 namespace SharpDisplay
    14 {
    15     /// <summary>
    16     ///
    17     /// </summary>
    18     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    19     public class Callback : ICallback, IDisposable
    20     {
    21 		private DisplayClient DisplayClient { get; set; }
    22 
    23 		public Callback(DisplayClient aClient)
    24         {
    25             DisplayClient = aClient;
    26         }
    27 
    28         public void OnConnected()
    29         {
    30             //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    31             //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    32 
    33             MessageBox.Show("OnConnected()", "Client");
    34         }
    35 
    36 
    37         public void OnCloseOrder()
    38         {
    39 			DisplayClient.Close();
    40             //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    41             //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    42 
    43             //MessageBox.Show("OnServerClosing()", "Client");
    44             //MainForm.CloseConnectionThreadSafe();
    45             //MainForm.CloseThreadSafe();
    46         }
    47 
    48         //From IDisposable
    49         public void Dispose()
    50         {
    51 
    52         }
    53     }
    54 
    55 
    56     /// <summary>
    57     ///
    58     /// </summary>
    59     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    60     public class Client : DuplexClientBase<IService>
    61     {
    62         public string SessionId { get { return InnerChannel.SessionId; } }
    63 
    64         public Client(ICallback aCallback)
    65             : base(new InstanceContext(aCallback), new NetTcpBinding(SecurityMode.None, true), new EndpointAddress("net.tcp://localhost:8001/DisplayService"))
    66         { }
    67 
    68         public void SetName(string aClientName)
    69         {
    70             Channel.SetName(aClientName);
    71         }
    72 
    73         public void SetLayout(TableLayout aLayout)
    74         {
    75             Channel.SetLayout(aLayout);
    76         }
    77 
    78         public void SetField(DataField aField)
    79         {
    80             Channel.SetField(aField);
    81         }
    82 
    83         public void SetFields(System.Collections.Generic.IList<DataField> aFields)
    84         {
    85             Channel.SetFields(aFields);
    86         }
    87 
    88         public int ClientCount()
    89         {
    90             return Channel.ClientCount();
    91         }
    92 
    93         public bool IsReady()
    94         {
    95             return State == CommunicationState.Opened || State == CommunicationState.Created;
    96         }
    97     }
    98 
    99 
   100     /// <summary>
   101     /// Handle connection with our Sharp Display Server.
   102     /// If the connection is faulted it will attempt to restart it.
   103     /// </summary>
   104     public class DisplayClient
   105     {
   106         private Client iClient;
   107         private Callback iCallback;
   108         private bool resetingConnection = false;
   109 
   110         //private MainForm MainForm { get; set; }
   111         public string SessionId { get { return iClient.SessionId; } }
   112         public string Name { get; private set; }
   113         private TableLayout Layout { get; set; }
   114         private System.Collections.Generic.IList<DataField> Fields { get; set; }
   115 
   116 
   117         public DisplayClient(/*MainForm aMainForm*/)
   118         {
   119             //MainForm = aMainForm;
   120             Name = "";
   121             Fields = new DataField[]{};
   122         }
   123 
   124         /// <summary>
   125         /// Initialize our server connection.
   126         /// </summary>
   127         public void Open()
   128         {
   129             iCallback = new Callback(this);
   130             iClient = new Client(iCallback);
   131         }
   132 
   133         /// <summary>
   134         /// Terminate our server connection.
   135         /// </summary>
   136         public void Close()
   137         {
   138             iClient.Close();
   139             iClient = null;
   140             iCallback.Dispose();
   141             iCallback = null;
   142         }
   143 
   144         /// <summary>
   145         /// Tells whether a server connection is available.
   146         /// </summary>
   147         /// <returns>True if a server connection is available. False otherwise.</returns>
   148         public bool IsReady()
   149         {
   150             return (iClient != null && iCallback != null && iClient.IsReady());
   151         }
   152 
   153         /// <summary>
   154         /// Check if our server connection is available and attempt reset it if it isn't.
   155         /// This is notably dealing with timed out connections.
   156         /// </summary>
   157         public void CheckConnection()
   158         {
   159             if (!IsReady() && !resetingConnection)
   160             {
   161                 //Try to reconnect
   162                 Open();
   163 
   164                 //Avoid stack overflow in case of persisting failure
   165                 resetingConnection = true;
   166 
   167                 try
   168                 {
   169                     //On reconnect there is a bunch of properties we need to reset
   170                     if (Name != "")
   171                     {
   172                         iClient.SetName(Name);
   173                     }
   174 
   175                     SetLayout(Layout);
   176                     iClient.SetFields(Fields);
   177                 }
   178                 finally
   179                 {
   180                     //Make sure our this state does not get out of sync
   181                     resetingConnection = true;
   182                 }
   183             }
   184         }
   185 
   186         public void SetName(string aClientName)
   187         {
   188             Name = aClientName;
   189             CheckConnection();
   190             iClient.SetName(aClientName);
   191         }
   192 
   193 
   194         public void SetLayout(TableLayout aLayout)
   195         {
   196             Layout = aLayout;
   197             CheckConnection();
   198             iClient.SetLayout(aLayout);
   199         }
   200 
   201         /// <summary>
   202         /// Set the specified field.
   203         /// </summary>
   204         /// <param name="aField"></param>
   205         /// <returns>True if the specified field was set client side. False means you need to redefine all your fields using CreateFields.</returns>
   206         public bool SetField(DataField aField)
   207         {
   208             int i = 0;
   209             bool fieldFound = false;
   210             foreach (DataField field in Fields)
   211             {
   212                 if (field.Index == aField.Index)
   213                 {
   214                     //Update our field then
   215                     Fields[i] = aField;
   216                     fieldFound = true;
   217                     break;
   218                 }
   219                 i++;
   220             }
   221 
   222             if (!fieldFound)
   223             {
   224                 //Field not found, make to use SetFields with all your fields at least once after setting your layout.
   225                 return false;
   226             }
   227 
   228             CheckConnection();
   229             iClient.SetField(aField);
   230             return true;
   231         }
   232 
   233         /// <summary>
   234         /// Use this function when updating existing fields.
   235         /// </summary>
   236         /// <param name="aFields"></param>
   237         public bool SetFields(System.Collections.Generic.IList<DataField> aFields)
   238         {
   239             int fieldFoundCount = 0;
   240             foreach (DataField fieldUpdate in aFields)
   241             {
   242                 int i = 0;
   243                 foreach (DataField existingField in Fields)
   244                 {
   245                     if (existingField.Index == fieldUpdate.Index)
   246                     {
   247                         //Update our field then
   248                         Fields[i] = fieldUpdate;
   249                         fieldFoundCount++;
   250                         //Move on to the next field
   251                         break;
   252                     }
   253                     i++;
   254                 }
   255             }
   256 
   257             //
   258             if (fieldFoundCount!=aFields.Count)
   259             {
   260                 //Field not found, make sure to use SetFields with all your fields at least once after setting your layout.
   261                 return false;
   262             }
   263 
   264             CheckConnection();
   265             iClient.SetFields(aFields);
   266             return true;
   267         }
   268 
   269         /// <summary>
   270         /// Use this function when creating your fields.
   271         /// </summary>
   272         /// <param name="aFields"></param>
   273         public void CreateFields(System.Collections.Generic.IList<DataField> aFields)
   274         {
   275             Fields = aFields;
   276             CheckConnection();
   277             iClient.SetFields(aFields);
   278         }
   279 
   280         public int ClientCount()
   281         {
   282             CheckConnection();
   283             return iClient.ClientCount();
   284         }
   285 
   286 
   287 
   288     }
   289 
   290 
   291 }