|
-
Aug 13th, 2013, 12:47 PM
#1
Exceptions in background threads
hey 
I'm writing a quick example of multi threading for someone and it got me thinking about how everyone else deals with exceptions raised on a background thread, as I kind of just made up my own way of handling them and getting the error message details back to the UI thread to be displayed to the user. Perhaps it is pretty much the same way as most people do it but I'm just curious if other people do it completely differently.
Lets say we have a program that has a button on it and when clicked that button disables most of the UI and shows a progress bar etc, then creates a new thread and gets that to run some long running operation (so that the GUI doesn't freeze while this long blocking operation is being run). If the long running operation throws an exception then we want to show that error message to the user, but even if it doesn't then we need to re-enable the UI and hide the progress bar etc to show that the operation has completed (and perhaps we need to return some results from this operation to be displayed in the UI). So this is how I would do that (the example is from WPF but it would be very similar in WinForms) :
vb.net Code:
Class MainWindow
Private Sub BtnSearch_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles BtnSearch.Click
'Normally I would disable the buttons on the UI and show the progress bar etc here as well
Dim BgThread As New System.Threading.Thread(AddressOf DoSomeWork)
BgThread.IsBackground = True
BgThread.Start()
End Sub
Private Sub DoSomeWork()
Dim ErrorMessage As String = String.Empty
Dim Results As List(Of SearchResultItem)
Try
Results = SomeLongRunningOperation()
Catch ex As Exception
ErrorMessage = ex.Message
Finally
SearchFinished(ErrorMessage, Results)
End Try
End Sub
Private Sub SearchFinished(ErrorMessage As String, Results As List(Of SearchResultItem))
If Me.Dispatcher.CheckAccess Then
'Normally I would re enable the UI and hide the progress bar here as well
If String.IsNullOrEmpty(ErrorMessage) Then
MessageBox.Show("Operation completed successfully - " & Results.Count & " results found")
Else
MessageBox.Show("Error encountered: " & ErrorMessage)
End If
Else
Me.Dispatcher.Invoke(New Action(Of String, List(Of SearchResultItem))(AddressOf SearchFinished), ErrorMessage, Results)
End If
End Sub
End Class
So basically if the operation on the background thread throws an exception then that gets stored in the ErrorMessage variable which will always get passed in to the method that is always called before the background thread terminates, and that is then used to determine if an exception occurred or not. Of course it should also check to see if the results list was Nothing but I left that out for the sake of keeping this example short and to the point. I've never had any problems with using this technique at all, but like I said I'm just curious to see if other people do something similar or if you use events or callbacks instead.
-
Aug 13th, 2013, 01:03 PM
#2
Re: Exceptions in background threads
then we want to show that error message to the user
Do we? Always? Even if there's not a thing that can be done about it? Even if the error message is in computerese? Whilst error messages are endlessly fascinating to us when we are debugging, I think we're inclined to forget that the user has absolutely no interest in all this esoterica and arcana. As a user, I don't give a damn about the terminal state of the oojamaflip whilst traversing the thingummy at the flobadob. All I want is the result I asked for and a simple yes or no to whether I got it with perhaps an indication of whether or not it's worth having another go. For the user being told there's an error is most of the time about as useful as those Danger Falling Rocks signs on roads. So what do you expect me to do about it?
A lot of applications it seems to me could benefit from an automatic retry or two rather than rushing to tell me completely useless details of an error. If it's something I can do something about like a mistyped value or a poorly chosen setting then say so but say so in English! Otherwise it's just way too much information!
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Aug 13th, 2013, 01:24 PM
#3
Re: Exceptions in background threads
I agree with dunfiddlin. I don't believe simply displaying the error would be of much use or care to the general Joe Blogs. How ever i would check agasint what exception and then decide according what ti display.
vb Code:
Dim result As String = String.Empty
Dim error As Exception = Nothing
Try
result = DoSomething()
Catch ex As Exception
error = ex
End Try
Me.OnDoSomethingCompleted(New DoSomethingCompletedEventArgs(result, error))
vb Code:
Private Sub DoSomethingCompleted(sender as Object, e As EventArghs)
If e.Error IsNot Nothing Then
If e.Error.GetType Is TypeOf(SomeException) Then
' Handle
Else
' Possible throw exception again?
End If
Else
' Handle the esult
Last edited by ident; Aug 13th, 2013 at 01:32 PM.
-
Aug 13th, 2013, 01:33 PM
#4
Re: Exceptions in background threads
 Originally Posted by ident
I agree with dunfiddlin. I don't believe simply displaying the error would be of much use or care to the general Joe Blogs. How ever i would check agasint what exception and then decide according what ti display.
vb Code:
Dim result As String = String.Empty Dim error As Exception = Nothing Try result = DoSomething() Catch ex As Exception error = ex End Try Dim args As New DoSomethingCompletedEventArgs(result, error) ' Handle
vb Code:
Private Sub DoSomethingCompleted(sender as Object, e As EventArghs) If e.Error IsNot Nothing Then If e.Error.GetType Is TypeOf(SomeException) Then ' Handle Else ' Possible throw exception again? End If Else ' Handle the esult
I'll be honest I'm not a big fan of checking exception types, because at the end of the day there are a hell of a lot of possible exception types to potentially catch and they don't really narrow it down that much. I mean if I catch an SqlException yeah I can tell the user there was a problem with something to do with SQL but that is pretty vague so personally I think it would be much better to just use the Message property of the exception (which is available on the base Exception class, so no need to check for specific types of exception) as that will have more detail.
Just to clarify though: my post is not really about general exception handling, I'm just asking how people specifically get the error details back from the background thread to the UI thread to be displayed (IF you did want to display them, like I do)
Last edited by chris128; Aug 13th, 2013 at 01:38 PM.
-
Aug 13th, 2013, 01:27 PM
#5
Re: Exceptions in background threads
lol ok not the kind of response I was expecting but I'll explain. All of the programs I make are aimed at IT admins, so they are generally quite interested in the error message details because a lot of the time they might actually be able to do something about it or at least understand what the problem is.
I don't think that even non IT people shouldn't be shown error messages though. For a start they need some message to tell them that something went wrong - there's nothing more annoying than a program silently failing. So if I'm going to tell them that something went wrong and the operation couldn't be completed, don't you think it would be useful if they had something to go on? Something that they can search google for or something that they can report to their IT department. Sure, sometimes it might be an error message that makes absolutely no sense to them but personally I think that is a lot better than just saying "Failed" for every single scenario. I used to work in IT and trust me if programs never told you the actual error messages it would make our lives a hell of a lot harder because you'd have absolutely no idea whether it was a bug in the program, a problem with the user's computer, a problem with the network, the server, etc etc. How would anyone ever fix anything if no error message details were displayed? A lot of the time the error message details are not aimed at the end user, they are aimed at the system admin that will be getting a phone call as soon as the user sees an error pop up.
Last edited by chris128; Aug 13th, 2013 at 01:35 PM.
-
Aug 13th, 2013, 01:48 PM
#6
Re: Exceptions in background threads
Ok let's base my response on the user needs the error message. I would personally create a error handling mechanism. It certainly would get annoying filling out error parameters to MessageBox.Show() every time an error happens. The Main form handles how we display this message.
vb Code:
''' <summary> ''' Raises all information accordingly to the status label. ''' </summary> ''' <remarks></remarks> Public Class NotifierHandler ''' <summary> ''' Represents the method that will handle the <see cref="NotifierHandler.Notifies">PostData</see> event of <see cref="Notifies" />. ''' </summary> ''' <remarks > ''' Notifies the current session state. ''' </remarks> Public Event Notifies As EventHandler(Of NotifierEventArghs) ''' <summary> ''' Raises the Notifies event. ''' </summary> ''' <param name="e">The Event Arguments.</param> Protected Overridable Sub OnNotifier(ByVal e As NotifierEventArghs) RaiseEvent Notifies(Me, e) End Sub Public Sub Exception(ByVal ex As Exception) Dim message As String = String.Format("ERROR: Unknown Exception ({0}).", ex.Message) Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the form authenticity key could not be obtained. ''' </summary> Public Sub ShowFormAuthKeyFail() Dim message As String = "Form authenticity key could not be obtained." Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the form url is invalid. ''' </summary> Public Sub ShowUrlInvalid(ByVal Url As String) Dim message As String = String.Format("The URI string '{0}' is invalid.", Url) Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the form Href is invalid. ''' </summary> Public Sub ShowHrefInvalid(ByVal Href As String) Dim message As String = String.Format("The relative URI string '{0}' is invalid.", Href) Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the request Failed. ''' </summary> Public Sub ShowRequestFailed(ByVal uri As String) Dim message As String = String.Format("Failed to create HttpWebRequest for '{0}'.", uri) Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the request failed. ''' </summary> Public Sub ShowRequestFailedReturnedStatus(ByVal uri As String, ByVal status As String) Dim message As String = String.Format("Request from '{0}' returned Status '{1}'.", uri, status) Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the response failed. ''' </summary> Public Sub ShowResponseFailed(ByVal uri As String) Dim message As String = String.Format("Failed to get response from '{0}'.", uri) Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the response status code is bad. ''' </summary> Public Sub ShowResponseIsBad(ByVal uri As String, ByVal code As Integer, ByVal status As String) Dim message As String = String.Format("Request from '{0}' returned StatusCode '{1}' ({2})", uri, code, status) Me.OnNotifier(New NotifierEventArghs(message)) End Sub ''' <summary> ''' Displays an error message that indicates the login has failed. ''' </summary> Public Sub ShowLoginError() Dim message As String = "Invalid user name or email address." Me.OnNotifier(New NotifierEventArghs(message)) End Sub End Class
Last edited by ident; Aug 13th, 2013 at 01:51 PM.
-
Aug 13th, 2013, 04:51 PM
#7
Re: Exceptions in background threads
 Originally Posted by ident
Ok let's base my response on the user needs the error message. I would personally create a error handling mechanism. It certainly would get annoying filling out error parameters to MessageBox.Show() every time an error happens. The Main form handles how we display this message.
...
Thanks, presumably you'd just have your event handler on the form/window marshal that onto the UI thread if required whenever it needs to show the error message. So how would your method look that is actually executed on the background thread then?
-
Aug 13th, 2013, 03:10 PM
#8
Re: Exceptions in background threads
How would anyone ever fix anything if no error message details were displayed? A lot of the time the error message details are not aimed at the end user, they are aimed at the system admin that will be getting a phone call as soon as the user sees an error pop up.
In other words it's ok to release software which is broken/incomplete or not properly configured cos the poor sap who buys it can mop up after you? No need to program and thoroughly test, chaps. We'll let the Try/Catch get us out of any scrapes.
I'll be honest I'm not a big fan of checking exception types, because at the end of the day there are a hell of a lot of possible exception types to potentially catch and they don't really narrow it down that much.
I rest my case!
Try/Catch should only ever be used for circumstances beyond the user's control; dropped internet connections, missing files, server collapse and the like. It's not there to clean up sloppy programming for you or as a catch all failsafe for your failure to thoroughly test an application on all relevant platforms. If you're prepared to let software leave the building that may still fail in circumstances very much under your control, I would have thought the last thing you'd want to do would be to let admins have the full error message and work out exactly where you went wrong!
To quote the great Michael Flanders on the news that the UK was introducing an annual MOT test for cars ...
So they've brought in this law where you have to have you car tested every year. It used to be every three years. Now it's one. There's even some talk of having them tested before they leave the factory but I don't suppose that'll ever catch on!
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Aug 13th, 2013, 04:29 PM
#9
Re: Exceptions in background threads
I'm really not sure where you got this idea from that I was suggesting the software is broken or incomplete :S I'm using the Try/Catch blocks to do exactly what you say - catch errors that are outside of my control (network timeouts etc). I'm totally confused as to why you think otherwise. If the error cause is something I could check for or handle then yes I would just show the user a message explaining what is preventing the operation from working - but what we're talking about has nothing to do with that. I don't see why you are so intent on suggesting I've got the wrong design philosophy when making my programs - all I asked was a simple question about how people get exception details from a background thread back to the UI thread and so far you haven't even attempted to answer that. All you've done is tell me I don't want to do that and that I make broken software simply because I use a Try/Catch block. Not that I should have to explain myself to you, but I make software (completely on my own) that is used by literally thousands of companies including some very large ones such as BP, HTC, HP etc etc and I often receive emails saying how pleased people are with the software and how much more reliable and robust it is compared to similar tools. I spend a hell of a lot of time making sure everything works as it should and in some cases think I even go a bit overboard with potential error handling (i.e. writing code to handle scenarios that I'm 99% sure won't ever happen). So no, I don't think I need lessons on how to do basic error handling and how/when to use a Try Catch block. If you're not going to read the question properly and not respond to it with an actual answer then please don't post anything at all.
EDIT: I read your post again and it looks like you seem to think me saying an error message is aimed at a system admin means that I'm suggesting the errors are programming related rather than an error outside of my control. That is not what I mean at all and you obviously don't know what a system admin does if you think that's the case. For a start a system admin wouldn't understand a programming related error message either - and even if they did they wouldn't be able to fix it because they're not programmers and they don't have the source code. The kind of errors I'm talking about being useful for system admins are things relating to network or disk issues etc, stuff that is completely out of my control but if I just simply showed a generic error message (or failed silently) as you suggested in your original post then how would the system admins have a clue that this was a network problem? If all the program says is "Failed" then they've got no idea whether this is a bug in the program (no that's not the same as sloppy programming - everyone has the occasional bug found in their software) or if its a problem with their network or their PC etc - they have no idea where to start.
Last edited by chris128; Aug 13th, 2013 at 04:35 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|