I am deleting a row inside a DataGridView and when there is no more row this pops up.
Private Sub materialsGridView_SelectionChanged(sender As Object, e As EventArgs) Handles materialsGridView.SelectionChanged
Try
materialSelectedindex = materialsGridView.CurrentRow.Index
Catch ex As Exception
materialSelectedindex = -1
End Try
End Sub
Private Sub delRowBtn_Click(sender As Object, e As EventArgs) Handles delRowBtn.Click
If (materialSelectedindex = -1) Then
MsgBox("Please select a row")
Return
End If
materialsGridView.Rows.RemoveAt(materialSelectedindex)
End Sub
Here is an image
Why is it not catching even though it is inside a try catch?
Look at the Exception Assistant window. See how the box is checked that says "Break when this exception type is thrown"? If you don't want the debugger to break when that exception type is thrown, uncheck that box. That is only happening because you're running in the debugger. If you run the application without debugging, which you can do either directly or using the VS toolbar or pressing Ctrl+F5, then the exception will be caught.
By the way, it's generally bad practice to catch the base Exception type. You should catch only the specific exceptions that you reasonably believe could be thrown. Otherwise, you might be allowing a situation that you didn't count on and which might end up causing data corruption or the like.
You should also generally avoid exceptions being thrown in the first place, by validating the data you intend to use. In your case, you should check whether CurrentRow is Nothing first and then only use it if it's not. You could do this:
materialSelectedIndex = If(materialsGridView.CurrentRow Is Nothing,
1,
materialsGridView.CurrentRow.Index)
or you could do this:
materialSelectedIndex = If(materialsGridView.CurrentRow?.Index, 1)
The first option is basically an If...Then...Else while the second option uses the first value unless it's Nothing, in which case it uses the second value. The ?. operator will stop evaluation of the expression if what precedes it is Nothing, otherwise it behaves like a regular . operator.
Related
I'm having a very strange problem in a VB application. I have a function written like this:
In the innermost condition, two statements are commented out here. These were found to have no effect on the strange behaviour. This is the minimal example I've found causing trouble.
(Note that the names of objects have been changed in this example.)
Private Sub MyForm_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles myDGV.CellValidating
Dim dgv As DataGridView = CType(sender, DataGridView)
Select Case dgv.Columns(e.ColumnIndex).Name
Case "uniqueColumn"
' Validate that the values in our unique column are unique.
For i As Integer = 0 To dgv.RowCount - 1
If i <> e.RowIndex Then
' Here i != j, so compare to the value...
If e.FormattedValue = dgv.Rows(i).Cells(e.ColumnIndex).FormattedValue Then
e.Cancel = True
'dgv.ShowRowErrors = True
'dgv.Rows(e.RowIndex).ErrorText = "Data in the unique column must be unique"
End If
End If
Next 'i
Case Else
' Perform no validation.
End Select
End Sub
What trouble, you ask? For some inexplicable reason, whenever the line
e.Cancel = True
is executed, afterwards, nearly all buttons and form widgets in the entire application, including even the close button in its window bar (what a user would use to exit the application) stop doing whatever they previously did and now call this event handler instead.
In other words, commenting out that line (and doing the validation manually when the form is submitted) fixes the problems. I'd like to know why this happens, though. Some pointers:
Here's a list of which things are not affected:
The minimize and maximize button in the top bar.
All objects in its menu bar.
This handler is private to its form class, it's not referenced anywhere else in the application.
I'm at a loss. Just how? What could possibly cause this?
e.Cancel is for stopping the validation when the input is deemed incorrect. This causes the cell to still have focus as the user is expected to correct whatever they did wrong. The CellValidating event will then be raised again whenever the cell is about to lose focus until your code deems the input to be correct.
You can use the Control.CausesValidation property to control whether a control (for instance a button) should raise validation events when it gains focus.
Checking on a best practice here.
I am calling a ThreadPool to run an Async process, specifically sending an SSL email with an attachment which seems to take a good long while.
This is just test code, I thought I would drop this in a Try Catch just incase something failed. But will the thread ever even come back here? I have tested this closing the web page, the browser, clicking the back button on the page. The email always makes it through.
Try
System.Threading.ThreadPool.QueueUserWorkItem(AddressOf DoAsyncWork) '
Catch ex As Exception
Throw ex
Exit Sub
End Try
I am not trying to force a failure, yet I guess, but I would like to know how best to trap if the thread fails.
Protected Sub DoAsyncWork(ByVal state As Object)
Dim oMyObject As New sendSSLemail
oMyObject.SSL(userName, , strMessageBody, emailAdd, , permFileLocation, , "CodeMsg")
End Sub
A more convenient way of doing work with the thread pool is to use Task.Factory.StartNew(Action). It returns a Task object which can be Awaited or blocked on with Wait.
Once the task completes, the Exception property of the Task can be used to determine whether an exception was thrown and unhandled by the task's subroutine. (If it's not Nothing, then the InnerException property has the real exception that was thrown.)
Dim task = Task.Factory.StartNew(AddressOf WorkFunction)
' do stuff that doesn't depend on WorkFunction having completed
task.Wait()
If task.Exception IsNot Nothing Then Throw task.Exception.InnerException
After a Throw, the sub is exited anyway (the call stack is unwound looking for a Catch), so the Exit Sub statement does nothing. Wrapping a QueueUserWorkItem call in a try block also does nothing, because any exception would occur on the other thread. You would only get exceptions thrown immediately by QueueUserWorkItem, which off the top of my head only includes complaints about the delegate being Nothing.
Asynchronous tasks can also return values. For more information on that, see the TaskFactory methods that return a Func(Of Task).
When copying and pasting a bit of sample code from MSDN, I came up with the error in the title - Variable '' hides a variable in an enclosing block,
All I copied was a very basic example of a try loop.
As it says in the suggestion "A common cause for this error is the use of Catch e As Exception inside an event handler. If this is the case, name the Catch block variable ex rather than e."
So, I did that, changed both e to ex and it worked, however, I don't understand why this doesn't cause the same error.
Can someone please explain better what the error is and why e causes it, and ex doesn't?
edit -
code example...
Try
Catch e As Exception
msgbox(e.Message)
End Try
.
Try
Catch ex As Exception
msgbox(ex.Message)
End Try
What I don't understand is why the first one causes the problem and the second one doesn't, to me, it is like... Using apples above, apple below - saying you can't use the same thing in both places, then changing both to oranges and suddenly letting it work. Surely the second is doing the same as the first.
You might want to paste the full code for the error to confirm but I would assume that the event handler defines a parameter called "e". Then when you put in the catch block it tries to define "e" as well, causing the error in question. Of course when the catch is defining "ex" instead of "e" then there is no name clash happening so it works.
Edit: Edited to add clearer example of what I assume is the breoken code.
I assume your breaking code looks like:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
Catch e As Exception
msgbox(e.Message)
End Try
End Sub
You can see the two declarations of e, one in ByVal e As System.EventArgs and the other at Catch e As Exception.
That error message means that you are declaring a variable with a name that already exists:
int abc = 0;
if (abc == 0) {
int abc = 1; // Error
}
This rule applies of course to try .. catch as well.
Yes. rename the variable causing the problem to a unique name.
The project I'm working on is almost ready to ship. Occasionally, I'll encounter an error that won't allow the program to continue running like an out of bounds or a memory limitation.
These kinds of errors
I've been fixing them as I find them, but I'm sure there are others. However, I'm leaving this position in a few days so I need the users to not encounter these.
Is there a way in Vb.net that anytime one of those errors wants to pop up, it can catch it with an message box to the user that says something like "Something really bad happened. Please restart program"?
If it's a winform, you can catch the errors by handling the Application.ThreadException event.
AddHandler Application.ThreadException, AddressOf UIThreadException
Private Shared Sub UIThreadException(ByVal sender As Object, ByVal t As ThreadExceptionEventArgs)
' Handle event here and show message
' Exception is in t.Exception
End Sub
Make sure there's no error in this error handler. I don't think it'll catch exception in other threads.
You can use the Try statement, which is a simple way to handle error.
Here is a simple example:
Try
'Do something
Catch ex As Exception
MsgBox("Error occured")
End Try
So I have this form that loads a page, and after the page is loaded I want to insert the source into RichTextBox1.Text
However after the page load the program crashes(?) and gives me this error
"An unhandled exception of type 'System.AccessViolationException' occurred in Awesomium.Windows.Forms.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
This is my code and it is worth mentioning that I am using awesomium for this!
Public Class Form1
Dim Thread As System.Threading.Thread
Dim html_source_code As String = ""
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Control.CheckForIllegalCrossThreadCalls = False
Thread = New System.Threading.Thread(AddressOf Load_Page)
Thread.Start()
End Sub
Private Sub Load_Page()
While html_source_code = ""
If WebControl1.IsDocumentReady Then
html_source_code = WebControl1.ExecuteJavascriptWithResult("document.documentElement.outerHTML").ToString()
RichTextBox1.Text = html_source_code
End If
End While
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Thread = New System.Threading.Thread(AddressOf Load_Page)
Thread.Start()
End Sub
End Class
Thanks in advance!
Here is your first clue...
Control.CheckForIllegalCrossThreadCalls = False
This is a pretty obvious red flag. You should never use this except perhaps for very specific debugging purposes, and for very good reason. Given that the remainder of your code is full of illegal cross thread calls, it's no wonder your program is crashing.
Every single line of code you have written that is executed in a worker thread is touching UI components. You cannot do this. See this post for examples : Cross-thread operation not valid
UI controls are continuously operated on by the main thread of your application. The main thread must be able to access them to handle their associated events, draw them to the screen, etc. If another thread is modifying their contents while the main thread is attempting to read or write to them then bad things happen.
Consider a text box that the main thread is attempting to draw to the screen. It obtains a reference to the location of the string that contains the textbox's text and, in the middle of reading the string, another thread modifies the string, invalidating the reference that the main thread is using. When the main thread tries to read, its existing reference now points to an invalid memory location and, voila, access violation.
In almost all circumstances you should never, ever set CheckForIllegalCrossThreadCalls to False. Leaving it set True will raise an exception, but it gives you the opportunity to see where the problematic code is and allows you to correct it. Setting it False simply hides the illegal call, which may or may not fail, and your application will be vulnerable to random, buggy failures when those illegal calls end up causing problems. Suggest you do some reading about how to write multithreaded .NET applications. A good start would be here : StackOverflow Search.
See also : How to: Make Thread-Safe Calls to Windows Forms Controls