Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. C# threading question: Invoke() fails with ObjectDisposedException

C# threading question: Invoke() fails with ObjectDisposedException

Scheduled Pinned Locked Moved C#
questioncsharpdebugginghelpannouncement
21 Posts 13 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Keith Vitali
    wrote on last edited by
    #1

    Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

    t = new System.Threading.Thread
    (delegate()
    {
    result = Init();
    });
    t.Start();
    dialog.ShowDialog();

    This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

    delegate void ProgressValueDelegate(int value);
    public void SetProgressValue(int value)
    {
    if (this.InvokeRequired)
    {
    ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
    this.Invoke(pvd, new object[] { value });
    }
    else
    {
    m_progressBar.Value = value;
    }
    }

    So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

    E F C H F 9 Replies Last reply
    0
    • K Keith Vitali

      Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

      t = new System.Threading.Thread
      (delegate()
      {
      result = Init();
      });
      t.Start();
      dialog.ShowDialog();

      This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

      delegate void ProgressValueDelegate(int value);
      public void SetProgressValue(int value)
      {
      if (this.InvokeRequired)
      {
      ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
      this.Invoke(pvd, new object[] { value });
      }
      else
      {
      m_progressBar.Value = value;
      }
      }

      So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

      E Offline
      E Offline
      Ennis Ray Lynch Jr
      wrote on last edited by
      #2

      Object Disposed exception has nothing to do with Invoke Required. I would suggest checking to see if the progress bar has been disposed before assigning its value.

      Need custom software developed? I do custom programming based primarily on MS tools with an emphasis on C# development and consulting. I also do Android Programming as I find it a refreshing break from the MS. "And they, since they Were not the one dead, turned to their affairs" -- Robert Frost

      K 1 Reply Last reply
      0
      • E Ennis Ray Lynch Jr

        Object Disposed exception has nothing to do with Invoke Required. I would suggest checking to see if the progress bar has been disposed before assigning its value.

        Need custom software developed? I do custom programming based primarily on MS tools with an emphasis on C# development and consulting. I also do Android Programming as I find it a refreshing break from the MS. "And they, since they Were not the one dead, turned to their affairs" -- Robert Frost

        K Offline
        K Offline
        Keith Vitali
        wrote on last edited by
        #3

        Thanks for your reply. I did check all that and the IsDisposed property is false. Here is the call stack

        Object name: ProgressForm'.
        at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
        at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
        at ProgressForm.SetProgressDescription(String description)
        at Mycomponent.UpdateProgressDialogDescription(String description)
        at Mycomponent.Initialize(Int32 hashCode, Int32 numSeries, Int32[] nInstances)
        at
        at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
        at System.Threading.ExecutionContext.runTryCode(Object userData)
        at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
        at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
        at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
        at System.Threading.ThreadHelper.ThreadStart()</ExceptionString></Exception></TraceRecord>
        An unhandled exception of type 'System.ObjectDisposedException' occurred in System.Windows.Forms.dll

        Cheers,
        Keith

        W 1 Reply Last reply
        0
        • K Keith Vitali

          Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

          t = new System.Threading.Thread
          (delegate()
          {
          result = Init();
          });
          t.Start();
          dialog.ShowDialog();

          This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

          delegate void ProgressValueDelegate(int value);
          public void SetProgressValue(int value)
          {
          if (this.InvokeRequired)
          {
          ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
          this.Invoke(pvd, new object[] { value });
          }
          else
          {
          m_progressBar.Value = value;
          }
          }

          So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

          F Offline
          F Offline
          Fayu
          wrote on last edited by
          #4

          Your code should read:

          if (this.InvokeRequired)
          {
             ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);                          
             this.Invoke(pvd, new object\[\] { value });
             return;
          }
          else
          {
             m\_progressBar.Value = value;
          }
          

          I usually check to see if ISyncronizeInvoke is implemented and work on interface. This is how it would look:

          ISyncronizeInvoke sync = (ISyncronizeInvoke)this;
          if (sync != null)
          {
              if(sync.InvokeRequired)
              {
                  ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);                          
                  object\[\] args = { value };
                  sync.Invoke(pvd, args);
                  return;
              }
              else
              {
                  m\_progressBar.Value = value; 
              }
          }
          
          K 1 Reply Last reply
          0
          • F Fayu

            Your code should read:

            if (this.InvokeRequired)
            {
               ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);                          
               this.Invoke(pvd, new object\[\] { value });
               return;
            }
            else
            {
               m\_progressBar.Value = value;
            }
            

            I usually check to see if ISyncronizeInvoke is implemented and work on interface. This is how it would look:

            ISyncronizeInvoke sync = (ISyncronizeInvoke)this;
            if (sync != null)
            {
                if(sync.InvokeRequired)
                {
                    ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);                          
                    object\[\] args = { value };
                    sync.Invoke(pvd, args);
                    return;
                }
                else
                {
                    m\_progressBar.Value = value; 
                }
            }
            
            K Offline
            K Offline
            Keith Vitali
            wrote on last edited by
            #5

            Tried both and they fail. It always fails at the Invoke() call.

            F 1 Reply Last reply
            0
            • K Keith Vitali

              Tried both and they fail. It always fails at the Invoke() call.

              F Offline
              F Offline
              Fayu
              wrote on last edited by
              #6

              is the value null?

              K 1 Reply Last reply
              0
              • F Fayu

                is the value null?

                K Offline
                K Offline
                Keith Vitali
                wrote on last edited by
                #7

                No, the value for the sync object is valid. It goes into the loop and when it hits invoke, it barfs. You can see the callstack in one of the previous posts. Thanks, Keith

                1 Reply Last reply
                0
                • K Keith Vitali

                  Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

                  t = new System.Threading.Thread
                  (delegate()
                  {
                  result = Init();
                  });
                  t.Start();
                  dialog.ShowDialog();

                  This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

                  delegate void ProgressValueDelegate(int value);
                  public void SetProgressValue(int value)
                  {
                  if (this.InvokeRequired)
                  {
                  ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                  this.Invoke(pvd, new object[] { value });
                  }
                  else
                  {
                  m_progressBar.Value = value;
                  }
                  }

                  So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

                  C Offline
                  C Offline
                  Chris Trelawny Ross
                  wrote on last edited by
                  #8

                  Have you done an experiment where the dialog is hidden before you even start the thread? This would avoid the possible race condition, and would demonstrate if the problem is indeed a race condition, or something else (the latter being true if you still get an exception in the invoke)? You could probably use the debugger (with a breakpoint in both threads, and stepping the dialog closed before stepping the background thread into SetProgressValue()) to force your way past the possible race condition.

                  1 Reply Last reply
                  0
                  • K Keith Vitali

                    Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

                    t = new System.Threading.Thread
                    (delegate()
                    {
                    result = Init();
                    });
                    t.Start();
                    dialog.ShowDialog();

                    This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

                    delegate void ProgressValueDelegate(int value);
                    public void SetProgressValue(int value)
                    {
                    if (this.InvokeRequired)
                    {
                    ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                    this.Invoke(pvd, new object[] { value });
                    }
                    else
                    {
                    m_progressBar.Value = value;
                    }
                    }

                    So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

                    H Offline
                    H Offline
                    HuntrCkr
                    wrote on last edited by
                    #9

                    I have had a similar problem many times. In a lot of my apps, I have a textbox that sits on a form, and any thread can write a line to it. I have poured over documentation, and never found a solution to whether the form has been closed or not. So, I simply added the following :

                    private volatile bool formClosed = false;

                    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
                    {
                    formClosed = true;
                    }

                    delegate void ProgressValueDelegate(int value);
                    public void SetProgressValue(int value)
                    {
                    if (this.InvokeRequired)
                    {
                    ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                    this.Invoke(pvd, new object[] { value });
                    }
                    else
                    {
                    if( formClosed == false )
                    {
                    m_progressBar.Value = value;
                    }
                    }
                    }

                    BTW, you can also move the if to before the if (this.InvokeRequired) to save yourself an Invoke call if it won't be doing anything in anycase.

                    L 1 Reply Last reply
                    0
                    • H HuntrCkr

                      I have had a similar problem many times. In a lot of my apps, I have a textbox that sits on a form, and any thread can write a line to it. I have poured over documentation, and never found a solution to whether the form has been closed or not. So, I simply added the following :

                      private volatile bool formClosed = false;

                      private void Form1_FormClosing(object sender, FormClosingEventArgs e)
                      {
                      formClosed = true;
                      }

                      delegate void ProgressValueDelegate(int value);
                      public void SetProgressValue(int value)
                      {
                      if (this.InvokeRequired)
                      {
                      ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                      this.Invoke(pvd, new object[] { value });
                      }
                      else
                      {
                      if( formClosed == false )
                      {
                      m_progressBar.Value = value;
                      }
                      }
                      }

                      BTW, you can also move the if to before the if (this.InvokeRequired) to save yourself an Invoke call if it won't be doing anything in anycase.

                      L Offline
                      L Offline
                      Luc Pattyn
                      wrote on last edited by
                      #10

                      HuntrCkr wrote:

                      you can also move the if

                      Not a good idea. Invoke puts the job in the input queue of the main thread; a "close this form" command could already be awaiting execution. You need to perform the test as late as possible. :)

                      Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                      Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                      H 1 Reply Last reply
                      0
                      • L Luc Pattyn

                        HuntrCkr wrote:

                        you can also move the if

                        Not a good idea. Invoke puts the job in the input queue of the main thread; a "close this form" command could already be awaiting execution. You need to perform the test as late as possible. :)

                        Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                        Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                        H Offline
                        H Offline
                        HuntrCkr
                        wrote on last edited by
                        #11

                        In fact, it doesn't make a difference. Common misunderstanding. Let me first put in the code snippet

                        public void SetProgressValue(int value)
                        {
                        if( formClosed == true )
                        {
                        return;
                        }

                        if (this.InvokeRequired)
                        {
                           ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);                
                           this.Invoke(pvd, new object\[\] { value });
                        }
                        else
                        {
                            m\_progressBar.Value = value;
                        }
                        

                        }

                        When SetProgressValue is called from another thread, the first thing that happens is the check if the form is closed already. Let's take you hypothetical situation where a FormClosing event is queued, but has not been executed yet. formClosed is false, so now this.InvokeRequired is checked. It's true so a call to SetProgressValue is queued as well. The FormClosing event fires, and formClosed is set to true. Next, the queued call to SetProgressValue occurs. First thing, we check formClosed which is now true, so the function is terminated immediately. The common misconception is that Invoke simply transfers the call to the correct thread, but in fact the function is called all over again. Another thing many people are not aware of is that the call to Invoke actually halts the thread until the Invoked delegate has been executed in the GUI thread, which can cause major slowdowns. Rather use BeginInvoke. It does the same thing in this scenario, but does not block the calling thread.

                        L 1 Reply Last reply
                        0
                        • K Keith Vitali

                          Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

                          t = new System.Threading.Thread
                          (delegate()
                          {
                          result = Init();
                          });
                          t.Start();
                          dialog.ShowDialog();

                          This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

                          delegate void ProgressValueDelegate(int value);
                          public void SetProgressValue(int value)
                          {
                          if (this.InvokeRequired)
                          {
                          ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                          this.Invoke(pvd, new object[] { value });
                          }
                          else
                          {
                          m_progressBar.Value = value;
                          }
                          }

                          So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

                          F Offline
                          F Offline
                          Fabio Franco
                          wrote on last edited by
                          #12

                          It seems that, for some reason, your dialog is beeing disposed (and with it, all it's controls). It's really difficult to know why without more code. But have you tried handling FormClosing event? There you could do this: e.Cancel = true; this.Hide(); Maybe that will work out for you, hiding instead of closing. Let me know if it solves your problem Regards, Fábio

                          1 Reply Last reply
                          0
                          • H HuntrCkr

                            In fact, it doesn't make a difference. Common misunderstanding. Let me first put in the code snippet

                            public void SetProgressValue(int value)
                            {
                            if( formClosed == true )
                            {
                            return;
                            }

                            if (this.InvokeRequired)
                            {
                               ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);                
                               this.Invoke(pvd, new object\[\] { value });
                            }
                            else
                            {
                                m\_progressBar.Value = value;
                            }
                            

                            }

                            When SetProgressValue is called from another thread, the first thing that happens is the check if the form is closed already. Let's take you hypothetical situation where a FormClosing event is queued, but has not been executed yet. formClosed is false, so now this.InvokeRequired is checked. It's true so a call to SetProgressValue is queued as well. The FormClosing event fires, and formClosed is set to true. Next, the queued call to SetProgressValue occurs. First thing, we check formClosed which is now true, so the function is terminated immediately. The common misconception is that Invoke simply transfers the call to the correct thread, but in fact the function is called all over again. Another thing many people are not aware of is that the call to Invoke actually halts the thread until the Invoked delegate has been executed in the GUI thread, which can cause major slowdowns. Rather use BeginInvoke. It does the same thing in this scenario, but does not block the calling thread.

                            L Offline
                            L Offline
                            Luc Pattyn
                            wrote on last edited by
                            #13

                            My mistake. You're right about the test, if it sits on the top of the method, it gets executed twice so it can't go wrong. However executing it twice all the time may be a high price to pay for potentially saving one thread switch when the form closes. I do not really agree on the BeginInvoke issue. While technically correct, I don't like the SetProgressValue method to behave synchronously when called on the main thread and asynchronously when called anywhere else. If there is a potential asynchronous operation, it should be reflected in the method name (BeginSetProgressValue?) and it'd better be consistent (as in: don't test InvokeRequired, just call BeginInvoke). Furthermore, having a mix of such Invoke and BeginInvoke patterns (several Controls each using their own little SetProgressValue method) could result in incomprehensible app behavior. :)

                            Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                            Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                            H P 2 Replies Last reply
                            0
                            • L Luc Pattyn

                              My mistake. You're right about the test, if it sits on the top of the method, it gets executed twice so it can't go wrong. However executing it twice all the time may be a high price to pay for potentially saving one thread switch when the form closes. I do not really agree on the BeginInvoke issue. While technically correct, I don't like the SetProgressValue method to behave synchronously when called on the main thread and asynchronously when called anywhere else. If there is a potential asynchronous operation, it should be reflected in the method name (BeginSetProgressValue?) and it'd better be consistent (as in: don't test InvokeRequired, just call BeginInvoke). Furthermore, having a mix of such Invoke and BeginInvoke patterns (several Controls each using their own little SetProgressValue method) could result in incomprehensible app behavior. :)

                              Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                              Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                              H Offline
                              H Offline
                              HuntrCkr
                              wrote on last edited by
                              #14

                              Luc Pattyn wrote:

                              My mistake. You're right about the test, if it sits on the top of the method, it gets executed twice so it can't go wrong. However executing it twice all the time may be a high price to pay for potentially saving one thread switch when the form closes.

                              Hey, no problem. I make mistakes all the time. Hence my motto There are two ways to write bug free software. Only the third method works though ;P As for the performance cost argument, I think it's highly dependent on the scenario.

                              Luc Pattyn wrote:

                              I do not really agree on the BeginInvoke issue.

                              I agree with you. In a large project or any other production level code, things should be done consistently, and all the things you mention are true. That is why I stated that in this simplified scenario, BeginInvoke doesn't really matter. If the function was even remotely more complex, or had more than 3 lines to execute with the synchronous vs. asynchronous path, it would be far more important. Glad we could agree :)

                              1 Reply Last reply
                              0
                              • L Luc Pattyn

                                My mistake. You're right about the test, if it sits on the top of the method, it gets executed twice so it can't go wrong. However executing it twice all the time may be a high price to pay for potentially saving one thread switch when the form closes. I do not really agree on the BeginInvoke issue. While technically correct, I don't like the SetProgressValue method to behave synchronously when called on the main thread and asynchronously when called anywhere else. If there is a potential asynchronous operation, it should be reflected in the method name (BeginSetProgressValue?) and it'd better be consistent (as in: don't test InvokeRequired, just call BeginInvoke). Furthermore, having a mix of such Invoke and BeginInvoke patterns (several Controls each using their own little SetProgressValue method) could result in incomprehensible app behavior. :)

                                Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                                Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                                P Offline
                                P Offline
                                Peter Trevor
                                wrote on last edited by
                                #15

                                I'm not sure how to satisfy Luc's issue over mixing sync and async behaviours, but how about this variation:

                                public void SetProgressValue(int value)
                                {
                                MethodInvoker method = delegate
                                {
                                if (!formClosed)
                                {
                                m_progressBar.Value = value;
                                }
                                };

                                if (InvokeRequired)
                                    BeginInvoke(method);
                                else
                                    method.Invoke();
                                

                                }

                                First, you don't need to worry about keeping the delegate's parameters aligned with the method's parameters (makes maintenance easier). Second, you shouldn't test boolean values against true/false (just take their value). Third, it uses the async BeginInvoke when not on the GUI thread.

                                L 1 Reply Last reply
                                0
                                • K Keith Vitali

                                  Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

                                  t = new System.Threading.Thread
                                  (delegate()
                                  {
                                  result = Init();
                                  });
                                  t.Start();
                                  dialog.ShowDialog();

                                  This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

                                  delegate void ProgressValueDelegate(int value);
                                  public void SetProgressValue(int value)
                                  {
                                  if (this.InvokeRequired)
                                  {
                                  ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                                  this.Invoke(pvd, new object[] { value });
                                  }
                                  else
                                  {
                                  m_progressBar.Value = value;
                                  }
                                  }

                                  So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

                                  C Offline
                                  C Offline
                                  CodeHawkz
                                  wrote on last edited by
                                  #16

                                  Hi there, I would love to get my hands on your code and experiment. I am way too lazy to write a new one. If you think you can write a small app that simulates your prob or share your code itself, please do so. I would love to solve the riddle. =]

                                  1 Reply Last reply
                                  0
                                  • K Keith Vitali

                                    Thanks for your reply. I did check all that and the IsDisposed property is false. Here is the call stack

                                    Object name: ProgressForm'.
                                    at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
                                    at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
                                    at ProgressForm.SetProgressDescription(String description)
                                    at Mycomponent.UpdateProgressDialogDescription(String description)
                                    at Mycomponent.Initialize(Int32 hashCode, Int32 numSeries, Int32[] nInstances)
                                    at
                                    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
                                    at System.Threading.ExecutionContext.runTryCode(Object userData)
                                    at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
                                    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
                                    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
                                    at System.Threading.ThreadHelper.ThreadStart()</ExceptionString></Exception></TraceRecord>
                                    An unhandled exception of type 'System.ObjectDisposedException' occurred in System.Windows.Forms.dll

                                    Cheers,
                                    Keith

                                    W Offline
                                    W Offline
                                    Ware Work
                                    wrote on last edited by
                                    #17

                                    at ProgressForm.SetProgressDescription(String description)

                                    It appears to be calling SetProgressDescription and not SetProgressValue that you have included previously. Is this the issue?

                                    WarePhreak Programmers are tools to convert caffiene to code.

                                    1 Reply Last reply
                                    0
                                    • P Peter Trevor

                                      I'm not sure how to satisfy Luc's issue over mixing sync and async behaviours, but how about this variation:

                                      public void SetProgressValue(int value)
                                      {
                                      MethodInvoker method = delegate
                                      {
                                      if (!formClosed)
                                      {
                                      m_progressBar.Value = value;
                                      }
                                      };

                                      if (InvokeRequired)
                                          BeginInvoke(method);
                                      else
                                          method.Invoke();
                                      

                                      }

                                      First, you don't need to worry about keeping the delegate's parameters aligned with the method's parameters (makes maintenance easier). Second, you shouldn't test boolean values against true/false (just take their value). Third, it uses the async BeginInvoke when not on the GUI thread.

                                      L Offline
                                      L Offline
                                      Luc Pattyn
                                      wrote on last edited by
                                      #18

                                      I like it, especially if you scrap the "Begin" of BeginInvoke. :)

                                      Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                                      Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                                      1 Reply Last reply
                                      0
                                      • K Keith Vitali

                                        Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

                                        t = new System.Threading.Thread
                                        (delegate()
                                        {
                                        result = Init();
                                        });
                                        t.Start();
                                        dialog.ShowDialog();

                                        This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

                                        delegate void ProgressValueDelegate(int value);
                                        public void SetProgressValue(int value)
                                        {
                                        if (this.InvokeRequired)
                                        {
                                        ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                                        this.Invoke(pvd, new object[] { value });
                                        }
                                        else
                                        {
                                        m_progressBar.Value = value;
                                        }
                                        }

                                        So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

                                        J Offline
                                        J Offline
                                        JOAT MON
                                        wrote on last edited by
                                        #19

                                        Just a thought - Have you checked to see if the thread is still alive? It may be that the closing form is triggering the thread itself to close or change states, preventing the continued use without restarting it.

                                        Jack of all trades ~ Master of none.

                                        1 Reply Last reply
                                        0
                                        • K Keith Vitali

                                          Hello, I have been struggling with some threading issues over the last couple of days. I am getting close to getting this thing to work but there are still a few niggles. So, I have a thread that is called as follows and after the thread starts, my application shows a modal dialog box. So far so good:

                                          t = new System.Threading.Thread
                                          (delegate()
                                          {
                                          result = Init();
                                          });
                                          t.Start();
                                          dialog.ShowDialog();

                                          This works fine and there are no problems. Now, the user can hide this dialog box and when that happens the subsequent code gets executed as expected and this is not a problem. Also, I use ShowDialog(), so hiding or calling Close() should not call dispose as indicated in the docs. Also, the dialog box is a singleton and lives for the duration of the application. Now, my dialog box has a progress bar which gets updated by the calling thread and the update method that gets executed is as follows:

                                          delegate void ProgressValueDelegate(int value);
                                          public void SetProgressValue(int value)
                                          {
                                          if (this.InvokeRequired)
                                          {
                                          ProgressValueDelegate pvd = new ProgressValueDelegate(SetProgressValue);
                                          this.Invoke(pvd, new object[] { value });
                                          }
                                          else
                                          {
                                          m_progressBar.Value = value;
                                          }
                                          }

                                          So, as soon as the dialog box is hidden, the subsequent call crashes at the Invoke() call. I think there is some race condition going on somewhere because in the debugger the InvoleRequired value is fasle. However, the code has already entered the 'if' condition. Does anyone know how I can handle this sort of situation? Thanks, Keith

                                          P Offline
                                          P Offline
                                          Patrick Fox
                                          wrote on last edited by
                                          #20

                                          How are you hiding the dialog box? After some googling, it appears you aren't the only one facing this problem. Most helpful responses seem to suggest using try / catch and ignoring ObjectDisposedExceptions. This might work, because if the problem happens when the dialog is hidden, the user won't expect the progress bar to increment, because it's not visible... http://www.devnewsgroups.net/windowsforms/t38313-parkingwindow-objectdisposedexception-system-windows-forms.aspx[^] http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.languages.csharp/2006-08/msg01372.html[^]

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups