Results 1 to 12 of 12

Thread: Thread abort error caused when closing Please Wait form

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jan 2008
    Location
    Essex, UK
    Posts
    149

    Thread abort error caused when closing Please Wait form

    Background Info: I need this please wait form to mask over areas of my program when they are re-drawing or under high cpu load. The please wait screen will need to be displayed multiple times, for eg when the program is loading, stopping recording, starting recording etc.

    I found a example on the internet for how to create a 'Please wait' screen, but I have been having some trouble getting it to work without errors. Below is a link to the code example i used:

    http://pundtnotes.blogspot.co.uk/200...ease-wait.html

    The above example works very well however i have found that as it uses 'thread.abort' to close the thread that creates the please wait form it can cause errors. After several runs (Display then close) it can sometimes cause a 'System.Threading.ThreadAbortException: Thread was being aborted.' exception error. The thread abort exception error will vary slightly depending on if the please wait form has a animated gif on it or a progress bar etc.

    I have tried numerous methods to try and get around this exception but cannot resolve the problem. I keep hearing that thread 'Abort' is a nasty way to close a thread and this has proven this fact. Does anyone know a way i can close the thread safely with no risk of exception errors?. I have tried using boolean values etc and the values cant be read due to 'cross thread' reasons etc.

    Really stuck, please help

    Thanks
    Last edited by appolospb; Aug 1st, 2012 at 09:50 AM.
    Development Enviroment: Visual Studio 2008, VB.NET

    Recommend Winspector, far better then SPY++
    http://www.windows-spy.com/

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,038

    Re: Thread abort error caused when closing Please Wait form

    I show the Please Wait form in the UI, and do the processing in the background. That link seems to want to do it in reverse, where the form is shown from a background thread. In my case, there is no thread to abort, since the form is just a non-modal form in the UI thread, so it can be closed like any other form.
    My usual boring signature: Nothing

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Jan 2008
    Location
    Essex, UK
    Posts
    149

    Re: Thread abort error caused when closing Please Wait form

    Hi

    Thanks for replying. Your post makes logical sense but I am a bit confused how I would put that theory into practice?. As the 'Please wait' form requires a animation to show to the user the program hasn't crashed it needs to be run from a thread otherwise the animation doesn't animate. I have tried in the past to just show a form using for eg 'form1.show' but the animation wont animate as the UI thread is busy doing other things. Obviously once you start using threads to load a form you then open yourself up to having to use thread.abort which causes nasty exception errors. Any further help would be greatly appreciated.

    Update:

    I have given your solution a try by running the 'Please wait' form from the UI thread and displaying it by simply issuing the command 'form1.show' and 'form1.close'. I found that as i have many tasks running from the UI thread the animation would not animate (Despite extensive multi threading in my program). To counteract this I tried to get some of the high cpu load tasks to run as threads to take the strain of the UI thread so the please wait would animate, I got mixed results. As I use a few SDK's in my program some features still cause strain on the UI thread even when they are run in their own dedicated thread. So it would appear that running the 'Please wait' on its own dedicated thread is the only way forward. Any ideas??
    Last edited by appolospb; Aug 2nd, 2012 at 04:52 AM.
    Development Enviroment: Visual Studio 2008, VB.NET

    Recommend Winspector, far better then SPY++
    http://www.windows-spy.com/

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,038

    Re: Thread abort error caused when closing Please Wait form

    Since I don't know what you are doing, I can't say anything specific. If the UI thread is doing lots of work that is not UI related, that is the source of the problem. If you can't shift the non-UI activities into background threads, you are pretty much stuck.

    One thing that you may be able to do would be to use a termination flag rather than Thread.Abort. That depends on the animation running in a loop, but that's usually how animation works. If you added a global variable (or at least one visible to both the UI and the animation thread), you could write something like this:

    Do While myFlag
    'Animate
    Loop

    As long as the flag was set, the animation would continue. When the flag was cleared, the animation, and the thread itself, could end. The animation thread could set the flag, and all the UI thread would have to do would be to clear the flag when it was time for the animation to end.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Jan 2008
    Location
    Essex, UK
    Posts
    149

    Re: Thread abort error caused when closing Please Wait form

    Thanks again for the reply.

    My program records video and audio and then burns them to DVD. It is quite a complex program with a lot of stages and areas where CPU load can be quite high hence the need for the 'Please wait'. The program uses multithreading extensively but still occasionally suffers from slow re-draw stages and refershing etc. I wanted to add the 'Please wait' to the below areas for eg:

    Load program
    -Display please wait (Nice animation or Progressbar marquee)
    Start Recording
    - Display please wait (Nice animation or Progressbar marquee)
    End Recording
    - Display pleasewait (Nice animation or Progressbar marquee)

    As the 'Please wait' in the code example just displays a form there is no definitive end for the thread so you have no choice but to abort the thread to kill the modal form. I have tried setting flags (booleans) but due to 'cross thread' preventing access to certian variables i cannot use this method. I tried adding a timer to the modal form and polling a variable for a value of 'True' to close but this didnt work as it couldnt read the variable.

    The code i am using for the 'Please wait' is exactly the same as the one in the link. Hope this gives some further clarification on the problem, thanks.
    Development Enviroment: Visual Studio 2008, VB.NET

    Recommend Winspector, far better then SPY++
    http://www.windows-spy.com/

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,038

    Re: Thread abort error caused when closing Please Wait form

    There is no cross-thread issue to Booleans, so if you are getting issues when doing that, you are doing something odd. Controls have thread affinity, but variables do not unless they are local variables declared within a method. As long as your variables are at class or global scope, then there isn't any cross-thread issue.

    What I was suggesting was that the thread would do something like this:

    1) Set variable to True
    2) Show form for the animation.
    3) loop on the animation while the variable is True.
    4) When the variable is set to False, close the form.
    5) Terminate.

    For one thing, you could make that whole animation be a separate exe that you run as a separate process, though that seems like it might be overkill. It could be a bit tricky getting the form to display on top, in that case, but that should be solvable.

    I guess the point to clarify is this bit about cross-threading, since that doesn't make any sense at all.
    My usual boring signature: Nothing

  7. #7

    Thread Starter
    Addicted Member
    Join Date
    Jan 2008
    Location
    Essex, UK
    Posts
    149

    Re: Thread abort error caused when closing Please Wait form

    Below is a copy of the VB.NET source code i have been experimenting with:

    http://app.brickftp.com/f/2918bcf94

    The boolean value i am setting to try and trigger the close of the 'Please wait' form thread fails to work, I am stuck as to why. The seperate '.exe' idea for the 'Please Wait' is a good idea but its a messy way of resolving the issue. Alternatively here is the code if you do not wish to download the sample program:

    Code:
    Public Class FrmMain
    
        Public LoadingFrm As New ClsLoadingFrm
        Public closeform As Boolean = False
    
        Private Sub BtnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnOpen.Click
            LoadingFrm.startthread("Loading PaceNet")
        End Sub
    
        Private Sub BtnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnClose.Click
            closeform = True ' This close method fails to work
            'LoadingFrm.closethread() ' This method successfully closed the form with the occasional risk of a thread.abort exception error
        End Sub
    
    End Class

    Code:
    Imports System.Threading
    
    Public Class ClsLoadingFrm
    
        Public Loading As System.Threading.Thread
    
        Sub startthread(ByVal Description As String)
    
            Try
                Loading = New Thread(AddressOf createform)
                Loading.Name = Description
                Loading.Priority = ThreadPriority.Normal
                Loading.Start()
            Catch ex As Threading.ThreadAbortException
    
            Catch ex As Exception
    
            End Try
    
        End Sub
    
        Sub createform()
    
            Dim newform As New FrmPleaseWait
    
            Try
                newform.DisplayMessage(System.Threading.Thread.CurrentThread.Name)
            Catch ex As Threading.ThreadAbortException
    
            Catch ex As Exception
    
            End Try
    
            Try
                newform.ShowDialog()
            Catch ex As Threading.ThreadAbortException
    
            Catch ex As Exception
    
            End Try
    
        End Sub
    
        Sub closethread()
    
            ' NOTE! - Below '.Abort' can occasionally cause thread.abort exception errors to occur
    
            Try
                If Loading.IsAlive = True Then
                    Try
                        Loading.Abort()
                    Catch ex As Threading.ThreadAbortException
    
                    Catch ex As Exception
    
                    End Try
                End If
            Catch ex As Exception
    
            End Try
    
        End Sub
    
    End Class

    Code:
    Imports System.Threading
    
    Public Class FrmPleaseWait
    
        Dim CheckForClose As System.Threading.Thread
    
        Public Sub DisplayMessage(ByVal Message As String)
            LblMessage.Text = Message
        End Sub
    
        Private Sub FrmPleaseWait_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Control.CheckForIllegalCrossThreadCalls = False
            Try
                CheckForClose = New Thread(AddressOf DoWork_CheckForClose)
                CheckForClose.Priority = ThreadPriority.Highest
                CheckForClose.Start()
            Catch ex As Exception
    
            End Try
        End Sub
    
        Sub DoWork_CheckForClose()
            ' Display please wait form until 'closeform' boolean is set to 'true'
    
            Do
                If FrmMain.closeform = True Then
                    Me.Close()
                End If
                CheckForClose.Sleep(300)
            Loop
    
        End Sub
    
        Private Sub frmPleaseWait_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
    
            Dim formwidth1 As Integer = Panel4.Width
            Dim formcentre1 As Integer = Panel4.Width / 2
            Dim labellengh1 As Integer = LblMessage.Width
            Dim labelcentre1 As Integer = LblMessage.Width / 2
            Dim centrepoint1 As Integer = formcentre1 - labelcentre1
    
            LblMessage.Location = New Point(centrepoint1, LblMessage.Location.Y)
    
        End Sub
    
    End Class
    Last edited by appolospb; Aug 3rd, 2012 at 05:39 AM.
    Development Enviroment: Visual Studio 2008, VB.NET

    Recommend Winspector, far better then SPY++
    http://www.windows-spy.com/

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,038

    Re: Thread abort error caused when closing Please Wait form

    That code gives you Illegal Cross Thread errors? That may have to do with the location of the CloseForm boolean. I have never tried this technique using a variable that is a member of a class other than the class that hold the thread itself. In this case, you have the boolean as a member of a different form, which is derived from control. I don't know where the thread affinity is located, but that could be the issue, since the form is a control. There are two things to try, one being quite a bit easier than the other:

    1) Move the Boolean to a module so that it is a global variable.

    2) Move the Boolean to the form where it is used...except that you are doing some odd things.

    In fact, the more I look at that, the more messed up it appears to be. You have the Loading Form create the Wait form in a thread. Then in the wait form, you have another thread that is running a perpetual polling event, and when the flag is true, it closes the current form. That really shouldn't work, because that means you are calling Me.Close from a different thread from the one that displayed the form. That alone should cause the exception you are seeing.

    That wasn't what I was suggesting. For one thing, I totally hate the idea of polling like that. It's not a total spin wait, since you add that Sleep statement in there, but it is still pretty close, and spin waiting is a bad idea. What I was suggesting was dependent on the animation itself running as a loop, but you didn't show anything about the animation. Is there no loop associated with the animation? All you currently appear to be doing is showing a message. In contrast, I have a similar type of form, except that I have a timer on it, and whenever the timer ticks I change the backcolor of the form in such a way that it will eventually cycle throught all possible colors in a very random, hypnotic, pattern. In my case, though, the form is part of the UI thread. Running forms from other threads can be difficult anyways. I didn't object to that because I know it can be done, and you had an example of doing that. Now it is looking like the animation itself may be a misunderstanding. Is there actual animation? If so, how is it done? Now that I think about it, there is a chance that the animation itself is the problem you are having. I was thinking of my simple color cycling, but if you are doing something more, then how much of the CPU are you eating up with the animation itself?
    My usual boring signature: Nothing

  9. #9

    Thread Starter
    Addicted Member
    Join Date
    Jan 2008
    Location
    Essex, UK
    Posts
    149

    Re: Thread abort error caused when closing Please Wait form

    Hi

    I provided a link in my last post to download the code so you could better understand the dilemma. Did you take a look at the sample code?. The animation is a progressbar marquee so requires no animation loop in order to animate. The orginal code is not of my design and was aquired from another website as detailed in my orginal post and source code link (Post 1). The orginal code did not use the boolean and this still suffered from a thread.abort exception when the 'Please wait' was closed. The exception errors seem to be associated with how the form is being displayed and closed rather than being anything to do with the recently added boolean close event.

    I am not sure the boolean method will work at this point. I have tried locating the boolean on the class, the main form and the please wait form as a global variable and its value does not get updated. Something with the threading is preventing this from working. The only way i can demonstrate this to you is by you viewing the code if you get a chance. I have spent many days trying to resolve this issue so if you have a better method for displaying a please wait box i would love to see a example piece of code.

    I have re-supplied the FTP link to the code as it expires after 7 days:

    http://app.brickftp.com/f/159db18f9
    Last edited by appolospb; Aug 13th, 2012 at 04:53 AM.
    Development Enviroment: Visual Studio 2008, VB.NET

    Recommend Winspector, far better then SPY++
    http://www.windows-spy.com/

  10. #10
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,038

    Re: Thread abort error caused when closing Please Wait form

    Well, I won't be looking at it in the next seven days, as I am about to disappear into the woods to pick up dead fish for a week.

    And that's probably about as bizarre as any reply in the history of this forum.
    My usual boring signature: Nothing

  11. #11

    Thread Starter
    Addicted Member
    Join Date
    Jan 2008
    Location
    Essex, UK
    Posts
    149

    Re: Thread abort error caused when closing Please Wait form

    Quote Originally Posted by Shaggy Hiker View Post
    Well, I won't be looking at it in the next seven days, as I am about to disappear into the woods to pick up dead fish for a week.

    And that's probably about as bizarre as any reply in the history of this forum.
    Ok, unfortunatley the 7 days is a limitation of our FTP. After a couple of weeks spent on trying to solve this (total time even before using the forums) i think ill have to quit on getting this to work anyway. Good luck with the fishing trip or conservation cleanup (whichever of the two it is). Thanks anyway.
    Development Enviroment: Visual Studio 2008, VB.NET

    Recommend Winspector, far better then SPY++
    http://www.windows-spy.com/

  12. #12
    Frenzied Member
    Join Date
    Jul 2011
    Location
    UK
    Posts
    1,335

    Re: Thread abort error caused when closing Please Wait form

    Firstly, I don't like the code you are using. I know very little about threading so can't give you an explanation as to why, but it just doesn't sit well. And that's apart from the whole Thread.Abort and consequent random errors. I did come up with an alternative, but owing to my inexperience with threading, I hesitate to submit it here. So let's stick with the Devil we know.........

    I suspect the reason it is not working is as explained in the thread http://www.vbforums.com/showthread.p...orms-Colliding from post#10 onwards; you are using default instances of frmMain on two separate threads.

    You use the following sub in form FrmPleaseWait

    vb Code:
    1. Sub DoWork_CheckForClose()
    2.     ' Display please wait form until 'closeform' boolean is set to 'true'
    3.  
    4.     Do
    5.         If FrmMain.closeform = True Then
    6.             Me.Close()
    7.         End If
    8.         CheckForClose.Sleep(300)
    9.     Loop
    10.  
    11. End Sub
    which is running on the thread 'CheckForClose'. The default instance of FrmMain you are accessing here is specific to that 'CheckForClose' thread and different to the default instance of FrmMain you see on your screen. Two different default form instances, two different closeform boolean variables. The closeform variable that is updated when you click the Close Button on the form on the screen is not the closeform variable you are checking in the above sub code.

    Easiest solution to this is to set the closeform boolean as a global variable in a module instead of in the form.


    Your troubles don't end there, though. The above sub is running on the 'CheckForClose' thread and is being used to close form FrmPleaseWait. However, FrmPleaseWait was created on yet another different thread (thread 'Loading' in class ClsLoadingFrm) so you will get a Cross-thread InvalidOperationException when executing Me.Close (I know you set Control.CheckForIllegalCrossThreadCalls = False , but you really shouldn't.)

    So, sticking with Shaggy's idea of checking for a change in the value of a flag, I would declare the flag as a global variable in a module and use a Timer on form FrmPleaseWait to check for when it changes instead of the third thread you are using at the moment. Your code then becomes:


    vb.net Code:
    1. Module Globals
    2.     Public closeform As Boolean = False
    3. End Module


    vb.net Code:
    1. Public Class FrmMain
    2.  
    3.     '   these are confusing names
    4.     '   as they are not actually Forms
    5.     Public LoadingFrm As New ClsLoadingFrm
    6.  
    7.  
    8.     Private Sub BtnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnOpen.Click
    9.         LoadingFrm.startthread("Loading PaceNet")
    10.     End Sub
    11.  
    12.     Private Sub BtnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnClose.Click
    13.         closeform = True
    14.     End Sub
    15.  
    16. End Class

    vb.net Code:
    1. Public Class FrmPleaseWait
    2.  
    3.     Public Sub DisplayMessage(ByVal Message As String)
    4.         LblMessage.Text = Message
    5.     End Sub
    6.  
    7.     Private Sub FrmPleaseWait_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    8.         Timer1.Interval = 300
    9.         Timer1.Enabled = True
    10.     End Sub
    11.  
    12.     Private Sub frmPleaseWait_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
    13.  
    14.         Dim formwidth1 As Integer = Panel4.Width
    15.         Dim formcentre1 As Integer = Panel4.Width / 2
    16.         Dim labellengh1 As Integer = LblMessage.Width
    17.         Dim labelcentre1 As Integer = LblMessage.Width / 2
    18.         Dim centrepoint1 As Integer = formcentre1 - labelcentre1
    19.  
    20.         LblMessage.Location = New Point(centrepoint1, LblMessage.Location.Y)
    21.  
    22.     End Sub
    23.  
    24.     Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
    25.         If closeform = True Then
    26.             '   must reset the timer and flag here
    27.             Timer1.Enabled = False
    28.             closeform = False
    29.  
    30.             Me.Close()
    31.         End If
    32.     End Sub
    33. End Class



    vb.net Code:
    1. Imports System.Threading
    2.  
    3. Public Class ClsLoadingFrm
    4.  
    5.     Public Loading As System.Threading.Thread
    6.  
    7.     Sub startthread(ByVal Description As String)
    8.  
    9.         Try
    10.             Loading = New Thread(AddressOf createform)
    11.             Loading.Name = Description
    12.             Loading.Priority = ThreadPriority.Normal
    13.             Loading.Start()
    14.         Catch ex As Threading.ThreadAbortException
    15.             '   you should always provide
    16.         Catch ex As Exception
    17.             '   code in Catch blocks
    18.         End Try
    19.  
    20.     End Sub
    21.  
    22.     Sub createform()
    23.  
    24.         Dim newform As New FrmPleaseWait
    25.  
    26.         Try
    27.             newform.DisplayMessage(System.Threading.Thread.CurrentThread.Name)
    28.  
    29.         Catch ex As Threading.ThreadAbortException
    30.             '  don't leave Catch blocks empty
    31.         Catch ex As Exception
    32.             '  as it makes debugging difficult
    33.         End Try
    34.  
    35.         Try
    36.             newform.ShowDialog()
    37.             newform.Dispose()
    38.  
    39.         Catch ex As Threading.ThreadAbortException
    40.             '  and can lead to unpredictable code
    41.         Catch ex As Exception
    42.             '  (and I don't mean fill them with comments!)
    43.         End Try
    44.  
    45.     End Sub
    46.  
    47. End Class

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width