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