i have this code on a form :
Function f1 as boolean
Try
------------
-----------
if condition
return true
else
return false
end if
Catch ex as Exception
Me.close
End try
End function
Private sub s1
if f1 then
instruction 1
else
instruction 2
end if
End sub
But if an exception occur inside f1 , the instruction Me.close
doesn't close the form instantly , but after
instruction 2 on s1 sub is executed.
How can i do to close the form instantly?
Thank you!
Depending on how you opened the form you should do a Me.dispose
Remarks from MSDN:
The two conditions when a form is not disposed on Close is when
(1) it is part of a multiple-document interface (MDI) application, and
the form is not visible; and
(2) you have displayed the form using
ShowDialog. In these cases, you will need to call Dispose manually to
mark all of the form's controls for garbage collection.
Me.Close() doesn't stop execution. Since you've handled the exception, execution continues after the call to f1. If you want execution to stop, you have to allow the exception to continue on:
Function f1 As Boolean
Try
'------------
'-----------
If condition Then
Return True
Else
Return False
End If
Catch ex As Exception
Me.Close()
Throw ' causes calling routines to stop executing as well
End Try
End Function
Related
I'm beginning to create a class to easily style my Windows apps. The concept is to just add the reference to the class on Form Load, then have the class automatically style each control on the form according to the properties I have for each control in the style class.
I've created a method where I just pass the Form to it, then loop through each control, check which type it is, then style it accordingly. No problem there so far; the problem is, if the form has a container control on it (i.e. a GroupBox), the items in it also need to be looped through, and checked for matches, and styled accordingly. So, if for example, I already have a check for a Button control in the main loop, with all of its style code there, then if the GroupBox has a button within it, it goes unstyled, unless I put the exact same check and style code in that loop as well ...
As one can imagine, checking for every single type of control + adding it's style code to each, and then repeating the exact same thing within another loop inside that loop, just to add all the same checks and style code, would turn into a TON of code (not to mention duplicated lines).
I'm wondering if maybe there's a smarter way of doing this, other than moving all of the style code into their own Subs, per control, then duplicating all of the same checks in both loops, and just calling each Sub for the styling? (Which is still messy, but at least all of that control style code isn't duplicated).
Here's the basic code I have right now; for the sake of clarity, I omitted all of the actual styling code per control (where you see the ' Style the control comments in each):
Public Sub MyStyle(ByVal zForm As Form, Optional lstIgnoreControl As List(Of Control) = Nothing)
Try
' Form
With (zForm)
' Style the basic Form properties
End With
Catch ex As Exception
End Try
For Each zCntl As Control In zForm.Controls
' Controls
If zCntl.HasChildren Then
For Each zChildCntl As Control In zCntl.Controls
If zChildCntl.GetType Is GetType(CheckBox) Then
' Style the Checkbox
End If
Next
End If
If IsNothing(lstIgnoreControl) = True OrElse lstIgnoreControl.Contains(zCntl) = False Then
Select Case zCntl.GetType
Case GetType(MenuStrip)
Try
' Style the menustrip
Catch ex As Exception
End Try
Case GetType(StatusStrip)
Try
' Style the Statusstrip
Catch ex As Exception
End Try
Case GetType(Label)
Try
' Style the Label
Catch ex As Exception
End Try
Case GetType(LinkLabel)
Try
' Style the LinkLabel
Catch ex As Exception
End Try
Case GetType(Panel)
Try
' Style the Panel
Catch ex As Exception
End Try
Case GetType(Button)
Try
' Style the Button
Catch ex As Exception
End Try
Case GetType(PictureBox)
Try
' Style the PictureBox
Catch ex As Exception
End Try
Case GetType(DataGridView)
Try
' Style the DataGridView
Catch ex As Exception
End Try
Case GetType(GroupBox)
Try
' Style the GroupBox
Catch ex As Exception
End Try
Case GetType(DateTimePicker)
Try
' Style the DateTimePicker
Catch ex As Exception
End Try
End Select
End If
Next
End Sub
The zCntl.HasChildren loop is the sub loop I'm referring to, where the redundency would all come in, that I'm hoping to avoid.
tl;dr but
Iterator Function allControls(c As Control) As IEnumerable(Of Control)
Yield c
For Each cc As Control In c.Controls
For Each ccc In allControls(cc)
Yield ccc
Next
Next
End Function
sample use:
For Each gb In allControls(zForm).OfType(Of GroupBox)
' ...
Next
or better put them all in a LookUp:
Dim types = allControls(zForm).ToLookup(Function(c) c.GetType)
For Each gb In types(GetType(GroupBox))
' ...
Next
I am using the following code in VB.Net (Winforms) to simply loop through a DataGridView and hide rows that are not needed.
Private Sub Overview_Workstream_Sort_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Overview_Workstream_Sort.SelectedIndexChanged
For Each row In Incident_Persons_List.Rows
If Incident_Persons_List.Rows(CInt(row)).Cells(7).Value.ToString.Contains(Overview_Workstream_Sort.SelectedItem.ToString) Then
Debug.Print("User found in workstream")
Incident_Persons_List.Rows(CInt(row)).Visible = True
Else
Incident_Persons_List.Rows(CInt(row)).Visible = False
End If
Next
End Sub
When the debugger gets to the first line of the IF statement, I get the following error:
An unhandled exception of type
'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
Additional information: Exception has been thrown by the target of an
invocation.
I've been trying everything I can think of to understand why this is. I've looked up the fault, but everyone seems to have completely different issues when this exception is thrown.
Is it something to do with how I am doing a compare?
UPDATE 1
I have removed the For Each and replaced it with For i = 0 to Incident_Persons_list.Rows.Count
I have removed the Cint instruction
The Try/Catch as revealed that the actual exception being thrown is:
Row associated with the currency manager's position cannot be made
invisible.
UPDATE 2
Everything is now working correctly with the below code:
Private Sub Overview_Workstream_Sort_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Overview_Workstream_Sort.SelectedIndexChanged
Try
For i = 0 To Incident_Persons_List.Rows.Count - 1
If Incident_Persons_List.Rows(i).Cells(7).Value.ToString.Contains(Overview_Workstream_Sort.SelectedItem.ToString) Then
Debug.Print("User found in workstream")
Incident_Persons_List.Rows(i).Visible = True
Else
'Your code that will throw the Exception
Incident_Persons_List.CurrentCell = Nothing
Incident_Persons_List.Rows(i).Visible = False
End If
Next
Catch ex As TargetInvocationException
'We only catch this one, so you can catch other exception later on
'We get the inner exception because ex is not helpfull
Dim iEX = ex.InnerException
Debug.Print(iEX.Message)
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End Sub
Thanks for the help!
TargetInvocationException :
The exception that is thrown by methods invoked through reflection
How to find out what's going on (because that exception is not really helpfull) ?
You must surroung the calling block with a Try/Catch structure, and then examine the InnerException caught :
Try
'Your code that will throw the Exception
Catch ex As TargetInvocationException
'We only catch this one, so you can catch other exception later on
'We get the inner exception because ex is not helpfull
Dim iEX = ex.InnerException
'Now you can do some stuff to handle your exception
Catch ex As Exception
'Here you catch other kinds of Exceptions that could occur in your code, if you want to...
End Try
And depending on the InnerException, you can now correct your code.
As your row variable is an enumerated element of Incident_Persons_List.Rows and not an index of the element in the collection I think you should replace.
Incident_Persons_List.Rows(CInt(row))
By
row
Or using a basic for structure instead of foreach. Somethink like
For row = 0 To Incident_Persons_List.Rows.Count - 1 Step 1
//SomeStuff
Next
I have a system tray application. The tray application has an icon and a context menu with some options. There is a menu called status which contains below toolstripmenuitems:
Start
Restart
Stop
They are enabled/disabled according to some conditions.
My system tray application, has a background thread does continuously check some conditions and do some work. Its main loop is below:
Do Until gAppExit Or Me.thdExit
' Check some conditions and do some work
Loop
gAppExit is a global variable that indicates whether user has exited from application through the 'exit' toolstripmenuitem.
thdExit indicates whether the thread should exit from the loop (I explain it later).
When user want to restart the background thread, he clicks on restart toolstripmenuitem and below sequence is done (Restart -> Halt -> WaitFinish):
Public Function ReStart() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Logger.Write("Task is not yet created!", LOGGING_CRITICAL_ERRORS_CATEGORY)
Return RESULT_ERROR
End If
result = Me.Halt()
If result <> RESULT_ERROR Then
result = Me.Start()
End If
Return result
End Function
Public Function Halt() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Logger.Write("Task is not yet created!", LOGGING_CRITICAL_ERRORS_CATEGORY)
Return RESULT_ERROR
End If
Me.thdExit = True
result = Me.WaitFinish()
Return result
End Function
Public Function WaitFinish() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Return RESULT_ERROR
End If
result = RESULT_ERROR
Try
'TODO:
Console.WriteLine("Wait thread to finish (before Join)...")
Me.ThreadBgWorker.Join()
'TODO:
Console.WriteLine("Thread finished... Continue restarting thread...")
Me.RetVal = True
result = Me.ThreadBgWorker.ManagedThreadId
Logger.Write(String.Format("Task ""{0}"" correctly stopped.", _
Me.ThreadBgWorker.Name))
Catch ex As Exception
Logger.Write(String.Format("Couldn't stop task ""{0}"": {1}", _
Me.ThreadBgWorker.Name, ex.Message), _
LOGGING_CRITICAL_ERRORS_CATEGORY)
End Try
Return result
End Function
Public Function Start() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Logger.Write("Task is not yet created!", LOGGING_CRITICAL_ERRORS_CATEGORY)
Return RESULT_ERROR
End If
result = RESULT_ERROR
Me.thdExit = False
Try
If Me.ThreadBgWorker.ThreadState = Threading.ThreadState.Stopped Then
Me.Create()
End If
Me.ThreadBgWorker.Start() ' Start the new thread.
result = Me.ThreadBgWorker.ManagedThreadId
Logger.Write(String.Format("Task ""{0}"" correctly started.", _
Me.ThreadBgWorker.Name))
Catch ex As Exception
Logger.Write(String.Format("Couldn't start task ""{0}"": {1}", _
Me.ThreadBgWorker.Name, ex.Message), _
LOGGING_CRITICAL_ERRORS_CATEGORY)
End Try
Return result
End Function
Note that on Halt function, it awaits thread to finish by calling Me.ThreadBgWorker.Join() on function WaitFinish. Before calling WaitFinish function, thdExit is set to true in order to background thread can exit from main loop:
Do Until gAppExit Or Me.thdExit
' Check some conditions and do some work
Loop
ChangeStatusToStopped()
on exit loop, ChangeStatusToStopped() is called, and it is as below:
Private Delegate Sub ChangeStatusToStoppedDelegate()
Public Sub ChangeStatusToStopped()
' TODO:
Console.WriteLine("Changing status to stopped...")
System.Windows.Forms.Application.DoEvents()
If MainMenu.InvokeRequired Then
'TODO:
Console.WriteLine("Invoke required!")
MainMenu.Invoke(New ChangeStatusToStoppedDelegate(AddressOf ChangeStatusToStopped))
Else
'TODO:
Console.WriteLine("Invoke NOT required!")
Me.submnuStart.Enabled = True
Me.submnuReStart.Enabled = False
Me.submnuStop.Enabled = False
End If
' TODO:
Console.WriteLine("Status changed to stopped.")
End Sub
What it does is to enable Start toolstripmenuitem and disable restart and stop toolstripmenuitems in the UI.
The problem is:
Within ChangeStatusToStopped method, when MainMenu.InvokeRequired is true, it calls:
MainMenu.Invoke(New ChangeStatusToStoppedDelegate(AddressOf ChangeStatusToStopped))
and then it gets stuck there, that is, else body:
Me.submnuStart.Enabled = True
Me.submnuReStart.Enabled = False
Me.submnuStop.Enabled = False
is never executed. It seems like main thread is busy or some other problem in message pump.... Any ideas?
I have seen that line:
Me.ThreadBgWorker.Join()
in WaitFinish() function is reached before background thread exits main loop and despite thdExit has been set to true before doing Me.ThreadBgWorker.Join(), once join is performed, application gets stuck, background thread cannot exit main loop (seems application is busy or frozen).
I'm trying to implement tasks in my program. I launch a task that will produce a log file, and after, I want to update the label to say "Log sucessfully saved".
Here is my code
Private Function Createlog(ByVal mylist As List(Of classTest))
Dim sw As New StreamWriter("log_list.log")
For index = 1 To mylist.Count - 1
sw.WriteLine(mylist(index).comments)
Next
sw.Close()
Try
Me.Invoke(UpdateLabel("Log sucessfully saved"))
Catch ex As Exception
End Try
Return 1
End Function
Private Function UpdateLabel(ByVal text As String)
Label1.Text = text
Return 1
End Function
I launch the task from the Main form in the Load() :
Dim tasktest = Task(Of Integer).Factory.StartNew(Function() Createlog(theList))
(I don't know if it is better to use the factory or declare as a task and then task.Start())
I have the error on the label update :
Cross-thread operation not valid: Control 'Label1' accessed from a thread
other than the thread it was created on.
Could you please explain why it doesn't work with the invoke method ? And do you have an alternative solution ?
Thanks for your help
First, UpdateLabel should be a Sub, not a Function. Second, this line is wrong:
Me.Invoke(UpdateLabel("Log sucessfully saved"))
Read it again. You are, in order, executing the UpdateLabel function, then passing the result of that function to Me.Invoke (if you used Sub instead of Function, the compiler should have warned you about the error).
This doesn't raise any compiler errors because a Function declared without As [Type] is defaulted to As Object, that can be cast to anything. It should be:
Me.Invoke(Sub()
UpdateLabel("Log sucessfully saved")
End Sub)
To simplify, your code can be rewritten like this:
Private Sub Createlog(ByVal mylist As List(Of classTest))
Dim sw As New StreamWriter("log_list.log")
For index = 1 To mylist.Count - 1
sw.WriteLine(mylist(index).comments)
Next
sw.Close()
Me.Invoke(Sub()
Label1.Text = "Log sucessfully saved"
End Sub)
End Sub
im trying to access a rich textbox on another form im using the following code to do so:
Private Delegate Sub StringDelegateChat(text As String, window As ChatWindow)
Private Sub AppendTextChatWindows(text As String, window As ChatWindow)
Try
If window.RichTextBox1.InvokeRequired Then
window.Invoke(New StringDelegateChat(AddressOf AppendTextChatWindows), text, window)
Else
window.RichTextBox1.AppendText(text)
window.RichTextBox1.SelectionStart = window.RichTextBox1.Text.Length
window.RichTextBox1.ScrollToCaret()
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
but i get the cross thread operation not valid error, i think it does this because it misses out the window.invoke part of the if statement. i also tried replacing theIf window.RichTextBox1.InvokeRequired Then to If InvokeRequired Then but it gets caught in a continues loop and a stack overflow error is thrown.
Thanks
Houlahan
I believe, on line 5, window.Invoke should be changed to window.RichTextBox1.Invoke.
Private Delegate Sub StringDelegateChat(text As String, window As ChatWindow)
Private Sub AppendTextChatWindows(text As String, window As ChatWindow)
Try
If window.RichTextBox1.InvokeRequired Then
window.RichTextBox1.Invoke(New StringDelegateChat(AddressOf AppendTextChatWindows), text, window)
Else
window.RichTextBox1.AppendText(text)
window.RichTextBox1.SelectionStart = window.RichTextBox1.Text.Length
window.RichTextBox1.ScrollToCaret()
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Have you tried:
Private Sub AppendTextChatWindows(text As String, window As ChatWindow)
Try
If window.RichTextBox1.InvokeRequired Then
window.RichTextBox1.BeginInvoke(New StringDelegateChat(AddressOf AppendTextChatWindows), text, window)
Exit Sub
Else
window.RichTextBox1.AppendText(text)
window.RichTextBox1.SelectionStart = window.RichTextBox1.Text.Length
window.RichTextBox1.ScrollToCaret()
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Basically, I am asking about BeginInvoke rather than Invoke. Although I would expect, as another poster mentioned, that you should be using the same thing you check the required against to invoke. (ie both window.invokeRequired & window.BeginInvoke or the control)
I cant see any errors in your code. You might want to check for any events that are fired when updating the RichTextbox. They might be causing a cross threading.
As a workaround to your problem, working with objects, you are less likely o encounter cross threading problems.