do I have to call all the exposed dispose functions of the controls within a windows form in the overriden dispose function? - winforms

I have a windows form that contains many controls e.g timers, gridviews, and binding sources etc, and all of these expose a dispose function. Do I have to call their dispose function in this
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
// do I have to write something here ???
base.Dispose(disposing);
}
also what does components.Dispose() exactly do?
thanks

Generally when you add controls onto your forms via the toolbox in Visual Studio, the controls will automatically be Disposed for you (in the protected override void Dispose method).
The only time you do need to manually dispose objects is when you manually create other disposable objects that implement the IDisposable interface, things like file handles (Stream, StreamReader...), GDI objects (Bitmap, Brush) and unmanaged resources. Manually releasing objects of this type ensure you follow good coding practice by releasing the resources you create.

No, the form will call Dispose for you.
What is Dispose for? This is taken from here IDispose
Use the Dispose method of this
interface to explicitly release
unmanaged resources in conjunction
with the garbage collector. The
consumer of an object can call this
method when the object is no longer
needed

The base.Dispose call invokes the System.Windows.Forms.Form.Dispose, which disposes menus and other form controls. The call ends up in System.Windows.Forms.Control.Dispose, which recursively disposes all child controls.
I guess you don't need to worry as long as your control is reachable from the form, either directly or transitively.

Related

WPF - Does HwndSource have to be disposed?

I'm using HwndSource in a WPF window, which is not the main window, in order to hook a window procedure (WndProc) to receive some messages:
WinSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
WinSource.AddHook(new HwndSourceHook(WndProc));
HwndSource implements IDisposable. MSDN is not clear about when/should I dispose it. The docs of HwndSource.FromHwnd explains the technique above:
You can use this method to return an HwndSource for a window that is not explicitly an interoperation window. The procedure for this is:
Create a WindowInteropHelper instance (providing the main Window as a constructor parameter).
Get the value of the Handle property from that WindowInteropHelper instance.
Pass that HWND value as a parameter to FromHwnd.
And then:
This technique can be useful if you then want to add general AddHook message processing to the window. However, whenever you create an HwndSource, you are also responsible for destroying it. This is true even if the Application object for an application HwndSource is disposed.
(the emphasis is mine)
However, at the HwndSource class doc, we see:
Object Lifetime
An HwndSource is a regular common language runtime (CLR) object, and its lifetime is managed by the garbage collector. Because the HwndSource represents an unmanaged resource, HwndSource implements IDisposable. [...] Calling Dispose explicitly from the interoperating code might be necessary for certain interoperation scenarios.
And regarding the hook:
The actual hooks are held by a weak reference. Therefore, make sure that you manage the lifetime of your hook delegate.
I can't give a full answer to this, but based on recent experience I can say that you should not dispose the HwndSource object too soon - specifically, not at all until the window it refers to is closed.
I was just debugging a scenario that was done like this:
using(var source = HwndSource.FromHwnd(window.HWnd()))
{
source.AddHook(hook);
}
The result of this was that the window became nonfunctional (no longer processing messages) right after the source was disposed.
Looking briefly into the reference source for FromHwnd(), it seems that it will always return you the same object for the same window. I think this is why you cannot dispose source just because your own code is done with it. Apparently HwndSource.Dispose() doesn't just clean up the HWndSource object, but some of the unmanaged window itself.
Having noticed this, now I also see the HWndSource documentation says:
Synchronously calling Dispose immediately destroys the Win32 window
which seems to be what I've observed.

Xaml parsing and multithreading

I'd like to load Xaml from code running in a background thread.
I understand I would have to sync with the dispatcher. However, it fails (throws an exception).
Why?
Here is the code
public MainWindow()
{
InitializeComponent();
Thread thread = new Thread(new ThreadStart(delegate
{
Dispatcher.Invoke(new Action(delegate
{
Content = XamlReader.Parse(
"<Button xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
Content='Hello World'/>");
}));
}));
thread.Start();
}
As Pavlo mentioned, you need to also set your content within the Dispatcher.
However, I will say - this is fairly useless.
Remember, when you call Dispatcher.Invoke or BeginInvoke, you're explicitly saying to run that code on the UI thread. By starting a background thread that does nothing but invoke back to the UI thread, you're effectively doing the same work on the UI thread, with the disadvantage of extra overhead being added to the system as well as harder debugging. In this case, you should just load the file directly.
This seems like a bad idea for a couple reasons. Are you expecting to get XAML fragments from a database or some other storage and you can't create the instances of these controls in C#? You could just create a Button directly.
Are you able to allow the data to drive your visualization? A good example of this is having a collection of ICommand objects (CommandViewModel, RelayCommand, etc) and a CommandView that you want to use to represent your command? In this case, it could be a <Button> with a binding to the CommandViewModel Title or Content property.
You're background thread could then be used to drive the population of data (collections, properties) and you're UI would be designed to flexibly accommodate the expected data patterns.

Access windows control from Backgroundworker DoWork

my issue is the following:
I have a windows form in which I've placed a LayoutPanel, when the forms Loads, multiple controls like: textboxes and labels are being added to the LayoutPanel.
Then on a button click, I need to process the data entered by the user on those dynamically created controls. For that purpouse I use a Backgroundworker which is supposed to take those controls and read their data.
My issue es that the Backgroundworker doesn't allows me to access the control from the DoWork Method, but I need to do it that way because I'll be reporting the progress of the operations.
Here are portions of my code to clarify the concept:
private void frmMyForm_Load(object sender, EventArgs e)
{
//I add multiple controls, this one is just for example
LayoutPanel1.add(TextBox1);
....
}
private void bgwBackground_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Control controlOut in LayoutPanel1.Controls)
{
//do some stuff, this one is just for example
string myString = controlOut.Name; //-> Here is the error, cant access controls from different Thread.
}
}
Setting text is simple just using a delegate, but how about getting the entire parent control to manipulate the child controls (just for getting info, I don't want to set any data, just need to Get Name, Text, stuff like that).
Hope I made myself clear, thank you all.
You can only access Windows Forms controls from the GUI thread. If you want to manipulate them from another thread, you will need to use the Control.Invoke method to pass in a delegate to execute on the GUI thread. In your situation, you should be able to do this:
private void bgwBackground_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Control controlOut in LayoutPanel1.Controls)
{
this.Invoke(new MethodInvoker(delegate {
// Execute the following code on the GUI thread.
string myString = controlOut.Name;
}));
}
}
I like to define an extension method that allows me to use the cleaner lambda syntax:
// Extension method.
internal static void Invoke(this Control control, Action action) {
control.Invoke(action);
}
// Code elsewhere.
this.Invoke(() => {
string myString = controlOut.Name;
});
As you are already aware, accessing control values from any thread other than the UI thread is a big no-no. I'd say one reasonable implementation is to use a .NET synchronization mechanism, such as a WaitHandle, to suspend your background thread while the UI thread updates a thread-safe data structure of your choice.
The idea is that your background thread notifies the UI thread (via the delegate mechanism you are already familiar with) that it needs information, then waits. When the UI is finished populating the shared variable with information, it resets the WaitHandle, and the background worker resumes.
Without writing out and testing all the code, let me give you a few resources:
WaitHandle.WaitOne documentation with example usage: http://msdn.microsoft.com/en-us/library/kzy257t0.aspx
My own favorite method of invoking an event on the UI thread: http://www.notesoncode.com/articles/2009/01/24/PowerfulExtensionMethodsPart1.aspx

When to unhook events in Silverlight

One-line summary: What is the best practice for unhooking event handlers created in the constructor of a UserControl in Silverlight2?
Background:
I am currently building a line-of-business application in Silverlight2. As Silverlight is a browser plugin, there is no concept of a Window - everything is done within UserControls. The way I'm handling different "forms" in the application is to have a top-level usercontrol that contains a Viewbox. To show different forms, I set the Child property of the Viewbox to different UserControls. My app has a singleton PageManager class that is called to open and close forms. The forms (UserControls) are stored in a stack. Opening a form puts it on the top of the stack, closing it removes it from the stack and shows the one below it.
I'm trying to follow the Model-View-ViewModel pattern. In each form (derived from UserControl), I have a ViewModel that manages all the data for the View. The ViewModel exposes events so the UI can be notified when operations such as load and save have completed.
In my form, I subscribe to the event in the constructor, after I've got the ViewModel
public partial class MyPage : UserControl
{
public MyViewModel ViewModel{get; set;}
// other constructors, which create the viewmodel and call the constructor below.
public MyPage(MyViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
this.LayoutRoot.DataContext = this.ViewModel;
// subscribe to event so we can do stuff
this.ViewModel.LoadCompleted += new MyViewModel.LoadCompletedEventHandler(ViewModel_LoadCompleted);
}
My question is: Now that I've subscribed to this event, when do I remove the handler? Do I create a destructor and do it there, or does that create a chicken-and-egg situation where the garbage collector wont destroy the object until all references (ie: the event handlers) are gone? Do I create an interface that the forms must implement that specifies an UnhookEvents function that's called when the form is closed by the PageManager?
Edit: Thanks for the responses. What about the situation where the ViewModel lasts longer than the form (UserControl)? Part of my app allows users to create what is quite a complex structure, but in 95% of cases it's much simpler. What I've did was create 2 forms that use the same ViewModel. Users can start filling out the simple form, then switch to advanced mode, which creates a new form, passing the ViewModel to it.
In the simple setup form:
private void AdvancedSessionSetupButton_Click(object sender, RoutedEventArgs e)
{
PageManager.GetPageManager().Close(this);
PageManager.GetPageManager().Open(new CreateSessionPage(this.ViewModel), "Create Session");
}
In the advanced setup form:
private void BasicSessionSetupButton_Click(object sender, RoutedEventArgs e)
{
PageManager.GetPageManager().Close(this);
PageManager.GetPageManager().Open(new CreateBasicSessionPage(this.ViewModel), "Create Session");
}
After PageManager.Close, the only things referencing the form are the events within the ViewModel. I guess that's where I should be unhooking them.
A destructor, more commonly known to C# programmers as Finalizers, is not necessary in this case. Assuming that ViewModel_LoadCompleted is a member function, it contains a pointer to "this" which you are giving to the ViewModel object which is fully contained by "this". The garbage collector should intelligently ignore this.
In this case, the correct thing to do is to not waste time unbinding them.
In general, you need to unbind an event handler when you pass "this" (explicitly, or implicitly) to some object which will hold that reference longer than the intended lifetime of "this". For example, if you set a handler on a parent control's event. Now the parent has a reference to you via the handler as well as in its Children controls collection. In this case, you should unbind when you are removed from the parent.
When in doubt, implement IDisposable and unbind in the call to Dispose().
Events are automatically unbinded when the garbage collector goes through your object.
But you can explicitly unbind them with the "-=" syntax at anytime:
this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted;
You can implement a destructor:
~MyPage
{
this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted;
}

How can a UserControl destroy itself?

When the user clicks on certain part of a window, I add a UserControl to the window's controls. The UserControl has a close button. What can I do in the UserControl's button handler to destroy the UserControl? There seems to be no .net analog to the Win32 DestroyWindow call, and there is no Close() method for a control. So far I have this:
private void sbClose_Click(object sender, EventArgs e)
{
Parent.Controls.Remove(this);
this.Dispose();
}
And, in case the parent needs to destroy the control, what are the steps? This is what I have so far:
Controls.Remove(control);
control.Dispose();
You're working in a managed code environment with garbage collection - there's nothing you can do to force the user control to be destroyed.
All you need to do, all you can do is to remove it from the parent and make sure there are no remaining references.
This will generally be sufficient:
private void sbClose_Click(object sender, EventArgs e)
{
Parent.Controls.Remove(this);
}
The only time you'll need more is if you tie things together with events, as you'll need to deregister those as well.
A control can't destroy itself. In terms of having a parent do it, you are on the right track. You can have the parent or another control call Dispose on it and remove all references to this control. Dereferencing the control this way will allow the GC to clean things up.

Resources