• Visitors can check out the Forum FAQ by clicking this link. You have to register before you can post: click the REGISTER link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. View our Forum Privacy Policy.
  • Want to receive the latest contracting news and advice straight to your inbox? Sign up to the ContractorUK newsletter here. Every sign up will also be entered into a draw to WIN £100 Amazon vouchers!

.NET 2 Multi Threaded UI

Collapse
X
  •  
  • Filter
  • Time
  • Show
Clear All
new posts

    .NET 2 Multi Threaded UI

    I have never exactly understood why UI controls are not thread safe. I guess there are perfectly good reasons, but it does strike me as unfortunate that there is no way (at least that I know of) of running the standard UI controls in a thread-safe mode.

    Predictably I now have a UI which needs to be thread safe.

    Typically of course I would want to write:-

    SomeTextBox.AppendText(someString)

    But of course I can't do that. So I can abstract the UI Updates into a different class and write instead:-

    XTUI.AppendText(someTextBox,someString)

    And:-

    Delegate Sub TSAppendTextCallback(ByVal t As TextBox, ByVal s As String)

    Shared Sub AppendText(byval someTextBox,someString)
    If t.InvokeRequired Then
    t.Invoke(New TSAppendTextCallback(AddressOf TSAppendText), t, s)
    Else
    t.AppendText(s)
    End If


    However, this is obviously a right royal pain in the butt. There must be a better way. The world and his dog must be writing multi threaded UI's. However, I have been unable as yet to find a better approach. Any suggestions?
    Last edited by ASB; 12 June 2009, 06:06.

    #2
    Can you use BackgroundWorker instead of creating your own threads?

    http://msdn.microsoft.com/en-us/libr...undworker.aspx

    Makes creating responsive multithreaded UI's easier.

    Alternatively, if you've had plenty of coffee this morning.

    http://blog.quantumbitdesigns.com/20...ler-revisited/

    Comment


      #3
      Problem is the threads aren't created by the UI in question so background worker is a bit yucky (but not impossible). I'm producing a bridge between two disparate sytems and theres a lot of bodging, I mean elegantly crafted and well though out principles, between them bridging the gap.

      I guess I'm stuck with the moethod I came up with earlier. Though I can probably improve it a bit with generics. It's just a lot of boring grunge to knock up.

      Of course I could always set Control.CheckForIllegalCrossThreadCalls to false and say "well it worked on the development box"

      Comment


        #4
        Why not create a set of thread safe controls?

        e.g.

        Code:
        public class SafeLabel : Label
        {
           delegate void SetString(string text);
           delegate string GetString();
           override public string Text
           {
              set
              {
                 if(InvokeRequired)
                 {
                    SetString setTextDel = delegate(string text)
                                                   { Text = text; };
                    Invoke(setTextDel,new object[]{value});
                 }
                 else base.Text = value;
              }
              get
              {
                 if(InvokeRequired)
                 {
                    GetString getTextDel = delegate(){ return Text; };
                    return (string)Invoke(getTextDel,null);
                 }
                 else return base.Text;
              }
           }
        }

        Comment


          #5
          Originally posted by DimPrawn View Post
          Why not create a set of thread safe controls?

          e.g.

          Code:
          public class SafeLabel : Label
          {
             delegate void SetString(string text);
             delegate string GetString();
             override public string Text
             {
                set
                {
                   if(InvokeRequired)
                   {
                      SetString setTextDel = delegate(string text)
                                                     { Text = text; };
                      Invoke(setTextDel,new object[]{value});
                   }
                   else base.Text = value;
                }
                get
                {
                   if(InvokeRequired)
                   {
                      GetString getTextDel = delegate(){ return Text; };
                      return (string)Invoke(getTextDel,null);
                   }
                   else return base.Text;
                }
             }
          }
          I'd hoped thats what somebody might have done, but I couldn't find any out there. However, I do recall last time I tried to inherit from the controls I had loads of problems with desgin time support (but this was VS 2003).

          I may well give it another go at some point soon.

          Comment


            #6
            Outside of .NET, I've found that updating Windows windows from threads other than the one used to create them often causes unpleasentness and is best avoided. I guess .NET is just enforcing that best practice.

            My approach to multithreading and GUIs would always be to update all the controls in the one GUI thread. The GUI thread can monitor the data to look for changes and update, or better still wait for an event which the worker thread(s) set to indicate the GUI needs to be updated.

            BTW you might want to use BeginInvoke, as Invoke will block until the GUI thread has completed the call. If the GUI thread is waiting on the worker thread, then you're in deadlock country.
            Will work inside IR35. Or for food.

            Comment


              #7
              Originally posted by VectraMan View Post
              Outside of .NET, I've found that updating Windows windows from threads other than the one used to create them often causes unpleasentness and is best avoided. I guess .NET is just enforcing that best practice.

              My approach to multithreading and GUIs would always be to update all the controls in the one GUI thread. The GUI thread can monitor the data to look for changes and update, or better still wait for an event which the worker thread(s) set to indicate the GUI needs to be updated.

              BTW you might want to use BeginInvoke, as Invoke will block until the GUI thread has completed the call. If the GUI thread is waiting on the worker thread, then you're in deadlock country.
              I guess it's the underlying thread affinity of the windows API thats the issue of course. Just up until .NET2 it was never really enforced (in .NET2 you can only be sure it's enforced in the IDE anyway). I am actually using BeginInvoke to avoid the deadlocks. Probably am going to go for events to keep the workers fully seperate from the UI anyway.

              Comment


                #8
                Bugger. Still seem to end up in the position where the UI doesn't properly see WM_PAINT. New plan. Retrofit dos 6.1 to the entire estate. Wonder if they'd like text mode windows.

                Comment

                Working...
                X