Fixing our client issue with static MainForm overwritten when using multiple clients.
authorsl
Fri, 15 Aug 2014 11:11:17 +0200
changeset 31f19b04646b6a
parent 30 c375286d1a1c
child 32 4c416d2878dd
Fixing our client issue with static MainForm overwritten when using multiple clients.
That was basically our issue with broadcast not working the way it should.
Client/Client.cs
Client/MainForm.cs
Client/Program.cs
Server/MainForm.cs
Server/Program.cs
     1.1 --- a/Client/Client.cs	Fri Aug 15 10:20:01 2014 +0200
     1.2 +++ b/Client/Client.cs	Fri Aug 15 11:11:17 2014 +0200
     1.3 @@ -14,9 +14,16 @@
     1.4      /// <summary>
     1.5      ///
     1.6      /// </summary>
     1.7 -    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
     1.8 +    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
     1.9      public class Callback : IDisplayServiceCallback, IDisposable
    1.10      {
    1.11 +        private MainForm MainForm { get; set; }
    1.12 +
    1.13 +        public Callback(MainForm aMainForm)
    1.14 +        {
    1.15 +            MainForm = aMainForm;
    1.16 +        }
    1.17 +
    1.18          public void OnConnected()
    1.19          {
    1.20              //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    1.21 @@ -32,8 +39,8 @@
    1.22              //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    1.23  
    1.24              //MessageBox.Show("OnServerClosing()", "Client");
    1.25 -            Program.iMainForm.CloseConnection();
    1.26 -            Program.iMainForm.Close();
    1.27 +            MainForm.CloseConnectionThreadSafe();
    1.28 +            MainForm.CloseThreadSafe();
    1.29          }
    1.30  
    1.31          //From IDisposable
    1.32 @@ -47,7 +54,7 @@
    1.33      /// <summary>
    1.34      ///
    1.35      /// </summary>
    1.36 -    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    1.37 +    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    1.38      public class Client : DuplexClientBase<IDisplayService>
    1.39      {
    1.40          public string Name { get; set; }
     2.1 --- a/Client/MainForm.cs	Fri Aug 15 10:20:01 2014 +0200
     2.2 +++ b/Client/MainForm.cs	Fri Aug 15 11:11:17 2014 +0200
     2.3 @@ -9,6 +9,7 @@
     2.4  using System.Windows.Forms;
     2.5  using System.ServiceModel;
     2.6  using System.ServiceModel.Channels;
     2.7 +using System.Diagnostics;
     2.8  
     2.9  
    2.10  namespace SharpDisplayClient
    2.11 @@ -32,7 +33,7 @@
    2.12  
    2.13          private void MainForm_Load(object sender, EventArgs e)
    2.14          {
    2.15 -            iCallback = new Callback();
    2.16 +            iCallback = new Callback(this);
    2.17              //Instance context is then managed by our client class
    2.18              InstanceContext instanceContext = new InstanceContext(iCallback);
    2.19              iClient = new Client(instanceContext);
    2.20 @@ -45,18 +46,57 @@
    2.21  
    2.22          }
    2.23  
    2.24 -        public void CloseConnection()
    2.25 +
    2.26 +       
    2.27 +        public delegate void CloseConnectionDelegate();
    2.28 +        public delegate void CloseDelegate();
    2.29 +
    2.30 +        /// <summary>
    2.31 +        /// 
    2.32 +        /// </summary>
    2.33 +        public void CloseConnectionThreadSafe()
    2.34          {
    2.35 -            if (IsClientReady())
    2.36 +            if (this.InvokeRequired)
    2.37              {
    2.38 -                //iClient.Disconnect();
    2.39 -                iClient.Close();
    2.40 +                //Not in the proper thread, invoke ourselves
    2.41 +                CloseConnectionDelegate d = new CloseConnectionDelegate(CloseConnectionThreadSafe);
    2.42 +                this.Invoke(d, new object[] { });
    2.43              }
    2.44 +            else
    2.45 +            {
    2.46 +                //We are in the proper thread
    2.47 +                if (IsClientReady())
    2.48 +                {
    2.49 +                    //iClient.Disconnect();
    2.50 +                    Trace.TraceInformation("Closing client: " + iClient.SessionId);
    2.51 +                    iClient.Close();
    2.52 +                    Trace.TraceInformation("Closed client: " + iClient.SessionId);
    2.53 +                }
    2.54  
    2.55 -            iClient = null;
    2.56 -            iCallback = null;
    2.57 +                iClient = null;
    2.58 +                iCallback = null;
    2.59 +            }
    2.60          }
    2.61  
    2.62 +        /// <summary>
    2.63 +        /// 
    2.64 +        /// </summary>
    2.65 +        public void CloseThreadSafe()
    2.66 +        {
    2.67 +            if (this.InvokeRequired)
    2.68 +            {
    2.69 +                //Not in the proper thread, invoke ourselves
    2.70 +                CloseDelegate d = new CloseDelegate(CloseThreadSafe);
    2.71 +                this.Invoke(d, new object[] { });
    2.72 +            }
    2.73 +            else
    2.74 +            {
    2.75 +                //We are in the proper thread
    2.76 +                Close();
    2.77 +            }
    2.78 +        }
    2.79 +
    2.80 +
    2.81          private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    2.82          {
    2.83              if (IsClientReady()) //Could catch exception instead
    2.84 @@ -64,7 +104,7 @@
    2.85                  iClient.Disconnect();
    2.86              }
    2.87  
    2.88 -            CloseConnection();
    2.89 +            CloseConnectionThreadSafe();
    2.90          }
    2.91  
    2.92          public bool IsClientReady()
     3.1 --- a/Client/Program.cs	Fri Aug 15 10:20:01 2014 +0200
     3.2 +++ b/Client/Program.cs	Fri Aug 15 11:11:17 2014 +0200
     3.3 @@ -8,8 +8,6 @@
     3.4  {
     3.5      static public class Program
     3.6      {
     3.7 -        public static MainForm iMainForm;
     3.8 -
     3.9          /// <summary>
    3.10          /// The main entry point for the application.
    3.11          /// </summary>
    3.12 @@ -21,8 +19,7 @@
    3.13  
    3.14              Application.EnableVisualStyles();
    3.15              Application.SetCompatibleTextRenderingDefault(false);
    3.16 -            iMainForm = new MainForm();
    3.17 -            Application.Run(iMainForm);
    3.18 +            Application.Run(new MainForm());
    3.19          }
    3.20      }
    3.21  }
     4.1 --- a/Server/MainForm.cs	Fri Aug 15 10:20:01 2014 +0200
     4.2 +++ b/Server/MainForm.cs	Fri Aug 15 11:11:17 2014 +0200
     4.3 @@ -12,6 +12,7 @@
     4.4  using System.Drawing.Imaging;
     4.5  using System.ServiceModel;
     4.6  using System.Threading;
     4.7 +using System.Diagnostics;
     4.8  //
     4.9  using SharpDisplayInterface;
    4.10  using SharpDisplayClient;
    4.11 @@ -386,6 +387,8 @@
    4.12  
    4.13          public void BroadcastCloseEvent()
    4.14          {
    4.15 +            Trace.TraceInformation("BroadcastCloseEvent - start");
    4.16 +
    4.17              var inactiveClients = new List<string>();
    4.18              foreach (var client in iClients)
    4.19              {
    4.20 @@ -393,6 +396,7 @@
    4.21                  {
    4.22                      try
    4.23                      {
    4.24 +                        Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
    4.25                          client.Value.OnServerClosing(/*eventData*/);
    4.26                      }
    4.27                      catch (Exception ex)
     5.1 --- a/Server/Program.cs	Fri Aug 15 10:20:01 2014 +0200
     5.2 +++ b/Server/Program.cs	Fri Aug 15 11:11:17 2014 +0200
     5.3 @@ -8,6 +8,8 @@
     5.4  {
     5.5      static class Program
     5.6      {
     5.7 +        //WARNING: This is assuming we have a single instance of our program.
     5.8 +        //That is what we want but we should enforce it somehow.
     5.9          public static MainForm iMainForm;
    5.10          /// <summary>
    5.11          /// The main entry point for the application.