In VB/C# .NET, does a dialog always have to be disposed of manually? - vb.net

I'm looking into disposing of resources and getting a little mixed up over the different ways to do it.
I've just found out that using Close() on a form shown with ShowDialog() only actually hides it and doesn't completely kill it off, so to speak. While this is useful for what I want at the moment, I'm now worrying about memory leaks elsewhere.
After using ShowDialog(), should I always call Dispose() on the form or use a Using block? Is there a difference? Or will the form be automatically disposed of when exiting the subroutine is was created in? For example, one of my typical simple usages:
Private Sub btnEdit_Click(sender As System.Object, e As System.EventArgs) Handles btnEdit.Click
Dim frm As New frmSomething()
frm.ShowDialog()
'frm is exited by clicking the X or using Close()
'At this point, frm is still in memory. Is it automatically disposed of
'after the End Sub here, or should I do frm.Dispose() ?
End Sub

It won't be automatically disposed, no. It may well not cause a problem, and there may well be a finalizer to do everything that's required, so the cost would just be some extra resources before the finalizer runs (and a longer delay before eventual GC) but it would be better to dispose it explicitly - ideally with a Using statement:
Using frm As New frmSomething()
frm.ShowDialog()
End Using

Related

How can I save application settings in a VB .NET application?

I made a projet a month ago in C# where I used application settings to save data. This time, I'm making a project in VB .NET where I need to store data. I have a textbox where the user input a certain key and if he gets it right, it sets a setting to true. Here's the code.
Public Class Form4
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If TextBox1.Text = ("CF4A438C1F68D" Or "7552B2C629D11" Or "9C9C94A73141A" Or "7EE3998DAB3D3" Or "FC4DABC9CA7EA" Or "FDEE4B1F2C113" Or "D773E97B47531" Or "AABBBF181D39A" Or "36F37B39D19A5") Then
Properties.Settings.Default.ActivatedVersion = True
Properties.Settings.Default.Save()
End If
End Sub
End Class
Unfortunately, when I write Properties, it doesn't work. How can I do this?
In VB, you use My.Settings rather than Properties.Settings.Default.
Also, you don't necessarily need to call Save explicitly as it will happen automatically, by default, when the application exits. It won't happen if the application crashes but, if you have done the right thing and handled the UnhandledException event, the application will not crash, even if an unhandled exception is thrown.

programmatically set win forms user controls to nothing on dispose

I have vb.net winforms application. It has memory leaks which is caused by a third party control. I am left with the option of reducing instead of eliminating the memory leaks.
The form has several user controls declared as Friend WithEvents. They are not GCed when the form is closed, because the form is in memory and it holds a reference to the user control. However, when I set the user control references to nothing on dispose, the memory leak is reduced.
Now I want to expand this to the whole application instead of just one form. How would I use reflection to scan through all the user controls and set them to nothing on dispose ? Interesting to note is that the user controls are declared using "Friend WithEvents" signature. Is it possible to somehow use this while scanning ?
As #Plutonix states, if you dispose of the control, it will invalidate and dispose of its child controls. If you believe they are using dynamic controls, you could just recursively dispose of the controls?
Sub DisposeControls(parentControl as Control)
For each control as Control in parentControl.Controls
If control.HasChildren() Then Call Me.DisposeControls(control)
control.Dispose()
Next
End Sub
Edit: should mention, I am unsure if code above will compile - treat as pseudocode.
I ended up doing this. Its not optimal but it works really well. I have all the forms inheriting a base form. In the disposed method of that form, I use this reflection code.
Private Sub BaseForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
NullifyReferencesOnDispose()
RemoveHandler Me.Disposed, AddressOf BaseForm_Disposed
End Sub
Protected Overridable Sub NullifyReferencesOnDispose()
Dim typ = CType(Me.GetType, Reflection.TypeInfo)
For Each fld In typ.DeclaredFields
fld.SetValue(Me, Nothing)
Next
End Sub

Cause program crash on purpose in VB.NET

I'd need a way to cause the program to crash on purpose when i click a button. But nothing comes to my mind that would still allow me to compile the program. any code that causes a hard crash for whatever reason. in particular i need it to close and not be able to continue. My beta testers need to test the recovery after crash feature. Thanks!
these things never happen when they should..
How about just throwing an unhandled exception?
Private Sub btnCrash_Click(sender As System.Object, e As System.EventArgs) Handles btnCrash.Click
Throw New System.Exception("The program has crashed catastrophically!")
End Sub
To effectively kill the process use Environment.FailFast() in a button click handler, like this:
Protected Sub buttonCrash_Click(sender As Object, e As EventArgs) Handles buttonCrash.Click
Environment.FailFast()
End Sub
This will not generate any exceptions, etc., it is the same as going to Windows Task Manager and killing the process.
Here is the documentation for Environment.FailFast Method (String)
How about the Environment.FailFast method?
Private Sub btn_click(...)
Environment.FailFast("Failure!")
End Sub

Backgroundworker - UI still not responsive until BGW completed

I implemented a BGW to my application in hopes of speeding up loading time for the starting window(40+ controls)
I will not post my whole code as it's far too long but will give you the gist of the code. I split big function calls that take time to complete alongwith a handful of controls and moved them into the BGW in hopes of asyncronously loading controls to help quicken the process.
It is understood that I have to move UI changing code to the ProgressChanged event or RunWorkerCompleted event, which I have done. I originally had all code thrown into the DoWork event and it was extremely fast but found out it's not safe so I had reworked it to move all UI-related oode to the ProgressChanged. It's not nearly as fast now and it seems that the BGW controls wait until the UI thread completes prior to changing the controls in the BGW_ProgressCHanged event. I never saw this 'lag' between the two when I had all the changes in DoWork. What can I do about this? Or can I at least had the BGW update the controls realtime rather than waiting for all controls are completed before updating all controls?
The responsiveness is lower as well as it locks up the window to wait for the BGW controls to update. Just looking for what could possibly be happening
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
SyncLock <globalVar>
BackgroundWorker1.ReportProgress(0, "Tom")
End SyncLock
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Dim value As String = DirectCast(e.UserState, String)
Select Case e.ProgressPercentage
Case 0
lblName.text = value
lblName.Visible = true
End Select
End Sub
You removed all evidence of the problem in your code, but the diagnostic is an excellent match. You have a fire hose problem. Your code is calling ReportProgress far too often.
Things go wrong when your ProgressChanged event handler needs more time than the time between ReportProgress calls. Which is like drinking from a fire hose, no matter how fast you swallow the water, you just can't keep up with the flow.
Which is what the UI thread experiences. When it finishes the call to your ProgressChanged event handler, there's yet more water, yet another request to call the handler. That relentlessly continues without the UI thread ever being able to keep up. It now doesn't get around to doing its normal duties anymore. Which means that your UI stops updating, paints are no longer performed. And it doesn't respond to input anymore.
This can last for a while after the worker thread stopped running, the UI is still trying to work down the backlog of requests. When it finally gets there, the UI suddenly springs back to life.
A simple way to diagnose this condition is to add this method call after the ReportProgress call:
System.Threading.Thread.Sleep(45)
Which slows down the worker thread enough to limit the number of ReportProgress() calls to no more than 21 per second. Which is plenty fast enough for human eyes, anything faster just looks like a blur so is wasted effort. If that fixes the problem then you found the cause.
Using Sleep() like this is otherwise an ugly Q&D solution for the problem, it of course also slows down your worker so its gets less work done. You'll have to improve your code so that this doesn't happen and just makes less ReportProgress calls.
One thing you might want to add before starting the worker:
Me.SuspendLayout()
Then, in the RunWorkerCompleted event:
Me.ResumeLayout()
That should suspend all layout logic until all the work is done, then update the entire form in 1 operation.
EDIT
Replace
BackgroundWorker1.ReportProgress(...)
With
DirectCast(sender, BackgroundWorker).ReportProgress(...)
And get rid of the synclock.
EDIT2
The correct way to feed the data to the DoWork event is through the DoWorkEventArgs.
Start work like this:
BackgroundWorker1.RunWorkerAsync(<globalvar>)
And access it like this:
Dim globalVarData As Object = e.Argument

Visual Basic 2008 - New Form on a different thread

My “form1” is just a simple page with buttons that launch different forms which do all the work, the "form1" code for the first four buttons is below.
What I want is for each form to run in a separate thread.
Public Class Main
Private Sub btnDownLoadStockPrices_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDownLoadStockPrices.Click
LoadStocksFromDownloadSite.Visible = True
End Sub
Private Sub btnLoadOptionsIntoDatabase_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoadOptionsIntoDatabase.Click
LoadOptionsIntoDatabase.Visible = True
End Sub
Private Sub btnVerifyDatabases_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnVerifyDatabases.Click
VerifyDatabase.Visible = True
End Sub
Private Sub btnAnalyzeStock_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnalyzeStock.Click
AnalyzeSingleStock.visible = True
End Sub
End Class
I’ve found plenty of code examples to have different buttons on a single form run a subroutine in a separate thread, but for some reason I can’t seem to apply it to an entire form.
I think it’s something simple, like I need to tie each new thread as a handle to each forms “load” routine, but I just can’t get it to work. I don’t care about “synchronizing” threads at all, as each form is really a completely different functional program.
Any help would be much appriciated!
This isn't very common; generally it's best to limit all UI stuff to a single thread. But if you're convinced that you need each form to run on a separate thread, you must take into account the Windows API event handling model. The [over]-simplified version is that each form must have its own message loop to remove event messages from the queue and process them, so if you want to open a form on a new thread, you need to create that message pump.
The easiest way to do that is using the Application.Run method, and let the .NET Framework handle creating that message pump for you. For example:
Dim frm As Form1 = New Form1()
Application.Run(frm)
From looking at the code shown in your question, I can't discern any possible reason why those forms would need to run on separate threads. You can call the Show method of multiple forms so that they will be displayed on the screen at the same time. They won't block each other as long as you don't use the ShowDialog method, which displays each as a modal dialog. This is the way so many applications display multiple toolbox windows and other kinds of forms on the screen at the same time.
If you need to do some type of processor-intensive calculation, you still don't need to run each on a separate thread. Spin up a background thread (the BackgroundWorker class makes this very simple) and update the appropriate form's UI using the Invoke method.
You can certainly do this on Win32 but I don't know how well this maps over to .net.
The essential issue is that window handles have thread affinity. So you really need all interaction with them to happen in that thread. Essentially this means that you create all the window handles associated with that form in its thread. You also need to run a message loop in the thread.
The reason that people usually run all the UI out of the main thread and handle long-running actions in separate threads is that it is easier that way. You should ask yourself again why you want to do it this non-standard way.
I suspect you are not quite seeing the full picture. The need for threads in a desktop app principally arises when you have long running actions. Usually you want to keep your UI responsive and providing feedback for the long running action. Doing so leads to threads.
However, in your proposed solution you now have a multitude of extra threads and complexity, and you are still faced with the original problem! A long running action on one of your forms will hang it unless you perform that action in a separate thread, and once again we reach the standard solution to the problem.