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.
StephaneLenclud@447
     1

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