What is happening when I close a form, which was opened using Show(), by using Dispose() instead of Close()? Can someone tell me in detail, what happening in the Dispose() method?
The basic difference between Close() and Dispose() is, when a Close() method is called, any managed resource can be temporarily closed and can be opened once again. It means that, with the same object the resource can be reopened or used. Where as Dispose() method permanently removes any resource ((un)managed) from memory for cleanup and the resource no longer exists for any further processing.
Or just a general statement. With the connection object calling Close() will release the connection back into the pool. Calling Dispose() will call Close() and then set the connection string to null.
Some objects such as a Stream implement IDisposable but the Dispose method is only available if you cast the object to an IDisposable first. It does expose a Close() method though.
I would always argue that you should call Dispose() on any object that implements IDisposable when you are through with the object. Even if it does nothing. The jit compiler will optimize it out of the final code anyway. If the object contains a Close() but no Dispose() then call Close().
You can also use the using statement on IDispoable objects
using(SqlConnection con = new SqlConnection())
{
//code...
}
This will call Dispose() on the SqlConnection when the block is exited.
Decompiling the two methods (Dispose and Close) it turns out that the latter performs two additional checks and then calls Dispose, just like this:
object[] objArray;
if (base.GetState(262144))
{
throw new InvalidOperationException(SR.GetString("ClosingWhileCreatingHandle", new object[] { "Close" }));
}
if (base.IsHandleCreated)
{
this.closeReason = CloseReason.UserClosing;
base.SendMessage(16, 0, 0);
return;
}
base.Dispose();
From documentation:
When a form is closed, all resources created within the object are closed and the form is disposed.
[...]
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.
Hope it helps.
Actually, in this case Close() and Dispose() is quite different:
Close closes the form by sending the appropiate Windows message. You will be able to open the form again using Open()
Dispose disposes the form resources altogether, and you won't be able to re-use the form instance again.
Related
In my console app I've been trying to start an STA thread and show a WPF window. I've succeeded showing the window, but I had issues with a library using Dispatcher (System.Reactive.Windows.Threading to be precised). I've fixed my problems using code from this doc - what I was missing was calling System.Windows.Threading.Dispatcher.Run() in the right moment.
But after reading this article carefully (and others) and examining Dispatcher's API I still don't know: how to tell WPF Dispatcher is correctly initialized and running? It'd be very useful for libraries requiring Dispatcher, if they could check it.
-- EDIT --
// Extending my question after #Peter Duniho remarks
Having C# console application I wanted to create a WPF window, where I'll observe, on Dispatcher, some data. The full code is here
So I have my program, where Main class looks like that:
static void Main(string[] args)
{
var observable = Observable
.Interval(TimeSpan.FromMilliseconds(500))
.TakeWhile(counter => counter < 10);
var thread = new Thread(() =>
{
new TestWindow(observable);
Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
Console.ReadKey();
}
I create here an observable with Interval operator, which ticks every 500 milliseconds, and I pass it to a TestWindow (code below) which I run on a separate thread. After 10 ticks I end the observable sequence.
TestWindow class:
public class TestWindow : Window
{
public TestWindow(IObservable<long> observable)
{
var isDispatcherInitialized = false;
Dispatcher.Invoke(() => isDispatcherInitialized = true, DispatcherPriority.ApplicationIdle);
if (!isDispatcherInitialized)
throw new ApplicationException("Dispatcher not initialized");
observable
.ObserveOnDispatcher()
.Window(TimeSpan.FromMilliseconds(600))
.Subscribe(_ => Console.WriteLine($"OnNext, observed on dispatcher with Window operator"));
}
}
In TestWindow I observe my observable on Dispatcher (ObserveOnDispatcher()), and I use Window operator.
PROBLEM with that code (tested on .NET Framework and on .NET Core 3.0 preview):
if I don't call Dispatcher.Run(); when starting STA thread, the validation where I call Dispatcher.Invoke() will be passed, but ObserveOnDispatcher() won't work correctly - subscription never stops, and the message: "OnNext, observed on dispatcher with Window operator" goes forever.
That's why I was wondering if I could detect Dispatcher's state.
It would be helpful if you would elaborate on this statement:
It'd be very useful for libraries requiring Dispatcher, if they could check it.
That is, why would it be useful?
For one, if you are using a third-party library (such as the Reactive Extensions (Rx) for .NET you mentioned, how would you knowing how to check for the dispatcher state help that library?
For another, what scenario doesn't work for you? Lacking a specific problem to solve, your question is fairly open-ended. It's not clear what type of answer would actually address your question.
That said, two things come to mind:
If you want to know if a dispatcher has been created for a given thread, you should call System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread); This will return null if not dispatcher has been created yet for that thread, or a reference to the dispatcher if it has been.
If you want to know that the dispatcher has completed initialization and is ready to dispatch things, it seems to me that the easiest thing to do is ask it to dispatch something, and when it does, it's ready. Using an overload of one of the invoking methods (BeginInvoke(), Invoke(), or InvokeAsync()) that takes a DispatcherPriority value, you can get fine-grained information regarding just what level of initialization has happened. For example, if you pass DispatcherPriority.Normal or DispatcherPriority.Send, when your delegate is invoked you'll know that the dispatcher is running. But if you pass DispatcherPriority.ApplicationIdle or DispatcherPriority.SystemIdle, you'll know that not only is the dispatcher running, but it's cleared its backlog of initial events to dispatch and the application is sitting waiting for user input.
This method call sits inside a class derived from DispatcherObject:
Dispatcher.Invoke(DispatcherPriority.Input, new ThreadStart(() =>
{
var exported = formatProvider.Export(original.Workbook);
Workbook = formatProvider.Import(exported);
}));
The method on the class is called by a backgroundworker in its DoWork delegate.
Workbook is Telerik's Workbook, as used by the RadSpreadsheetControl. Obviously, workbooks can only be accessed by the UI thread.
The above code throws an InvalidOperationException, saying
The calling thread must be STA, because many UI components require
this.
I don't really understand, as I thought that when invoking the actions with a Dispatcher, I would be calling it from the UI Thread, which is STA?
What am I missing here and how can this be fixed? Or should this work in general and the bug is somewhere else? What could be a reason then?
TL;DR: You must create this DispatcherObject inside your UI thread, not in a worker.
DispatcherObject.Dispatcher, which you are marshalling the operation to, is set to Dispatcher.CurrentDispatcher at the time of the object's construction. If the object is not created inside your existing UI thread then the documented behavior of CurrentDispatcher is to create a new dispatcher object associated with the thread. Later on, Invoke tries to marshal the call to that thread (which is not STA) resulting in the error.
It is not sufficient to use a class derived from DispatcherObject. You must use the Dispatcher from an existing UIElement created from XAML (or at least make sure, you create your class from inside the GUI thread where it picks the right Dispatcher).
I want to render a chart with the DevExpress ChartControl via the WiForm DrawToBitmap() function on a separate thread.
I try something like:
Form yourForm;
Thread thread = new Thread( () =>
{
yourForm = new HiddenForm();
Application.Run(yourForm);
});
thread.ApartmentState = ApartmentState.STA;
thread.Start();
yourForm.Invoke(chartRenderingFunction)
And simple make sure the Hidden never actually gets displayed. However, I don't need that hidden form, and there is a parameterless form of Application.Run(). However, if I run that, it doesn't return. So my question is once I call Application.Run() inside a thread, how do I inject code in it?
Well, you actually really do need that hidden window. The only way to get code to run on that thread. Somebody must call PostMessage() and that requires a window handle. Your Invoke() call makes that call. You really should use BeginInvoke() instead, there's no point in starting a thread if you are going to wait for the call to complete.
Using Application.Run(yourForm) is going to make the window visible. You can stop it from becoming visible by overriding the SetVisibleCore() method in your HiddenForm class:
protected override void SetVisibleCore(bool value) {
if (!this.IsHandleCreated) {
CreateHandle();
value = false;
ThreadReady.Set();
}
base.SetVisibleCore(value);
}
The CreateHandle() call is necessary to make sure that the window is created so it can process the PostMessage() notifications. Also note the added AutoResetEvent (ThreadReady), you are going to have to call ThreadReady.WaitOne() after calling the thread's Start() method to ensure that your BeginInvoke() call is going to work. Dispose the form to get the thread to exit or call Application.Exit().
Last but not least, be very careful with using non-trivial controls on that thread. A chart control certainly is not indicated. You'll have long-lasting problems if that control uses the SystemEvents class for example. Your worker thread will get it to raise events on that worker thread. But it won't be around anymore after the chart is printed. You'll now get the events fired on an arbitrary threadpool thread, very nasty. A deadlock is a common mishap, particularly apt to trigger when locking the workstation.
in WPF application I load a list of business objects by WCF to a listbox.
I want to load it in another thread and display a progressbar window.
But how? I need to call WCF service in the second thread and return its return value to the first (UI) thread. And this is the point I don't know. How to return?
Or what should be the correct workflow of calling for data at background and displaying of progress?
Now I:
- show the progress window
- create a new thread and call the WCF service
- return values <-- I don't know
- close window
But - is this workflow right?
I don't want to use a backgroundworker because I can call many different WCF services, not only one I could write into the DoWork method.
I have a WCFClient class in which I call all services I need. Here is a one of the methods (all methods are same only calls different services):
public class Client
{
public List<BusinessDto> GetBusinesses(int userID)
{
OnConnecting();
ServiceClient client = null;
BusinessDto[] dtos = null;
try
{
client = new ServiceClient();
dtos = client.GetBusinesses(userID);
}
catch
{
MessageBox.Show(Properties.Resources.ConnectionNotSucessful, Properties.Resources.ApplicationName, MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
if (client != null) client.Close();
OnClosing();
}
return dtos.ToList();
}
}
I'm catching an Onconnecting and OnClosing events of WCFClient and opening and closing a new window with progressbar.
But I do not call WCF services in a new thread, because I don't know how.
Thanks, I'm trying do that unsuccessfuly for a two days.
I don't want to use a backgroundworker because I can call many different WCF services, not only one I could write into the DoWork method.
Well, first, you can decide which of many DoWork methods you want to call at the time you prepare the BackgroundWorker. But you can also (and this is probably more maintainable) write a DoWork method of arbitrary complexity. You can write a DoWork method that takes an argument of type Client, and have it call a member method on that object, for instance. There's absolutely nothing limiting about this method.
The way I'd implement a progress bar window:
Implement a Task class that exposes three methods: SetUp, Execute, and TearDown, as well as a Status property, which is a struct containing int PercentComplete and string Message. Implement INotifyPropertyChanged.
Implement a protected UpdateStatus method that updates Status and raises PropertyChanged.
Build a modal window that implements a ShowDialog(Task t) method. In that method, call t.SetUp(), then create a BackgroundWorker.
Handle t.PropertyChanged and have the handler raise the BackgroundWorker's ProgressChanged event.
Have the BackgroundWorker's ProgressChanged event handler use t.Status to update the UI,
Have the BackgroundWorker's DoWork event handler call t.Execute().
Have its its RunWorkerCompleted event handler both handle exceptions (do not neglect this!) and call t.TearDown().
Build and test Task subclasses as needed.
Whenever you need to display a progress bar window, instantiate the appropriate Task, set whatever properties it needs, and then call ProgressBarWindow.ShowDialog(t). This will display the window and block and wait while the background process runs, updating the UI as it goes; it will return after t.TearDown() gets called.
BackgroundWorker is your friend. It does the thread marshalling for you, leaving you to worry about only doing the actual work.
Sorry to ask such a basic question but I seem to have a brain freeze on this one! I'm calling a COM (ATL) object from my WPF project. The COM method might take a long time to complete. I thought I'd try and call it asychronously. I have a few demo lines that show the problem.
private void checkBox1_Checked(object sender, RoutedEventArgs e)
{
//DoSomeWork();
AsyncDoWork caller = new AsyncDoWork(DoSomeWork);
IAsyncResult result = caller.BeginInvoke(null, null);
}
private delegate void AsyncDoWork();
private void DoSomeWork()
{
_Server.DoWork();
}
The ATL method DoWork is very exciting. It is:
STDMETHODIMP CSimpleObject::DoWork(void)
{
Sleep(5000);
return S_OK;
}
I had expectations that running this way would result in the checkbox being checked right away (instead of in 5 seconds) and me being able to move the WPF gui around the screen. I can't - for 5 seconds.
What am I doing wrong? I'm sure it's something pretty simple. Delegate signature wrong?
Thanks.
I'm sure you're right about the call to your ATL code getting marshaled to the GUI thread because the ATL code is STA, thereby blocking your GUI thread.
Two solutions:
Rearchitect the ATL portion to be MTA, which may not be feasible, or
Leave the ATL as STA but initially construct the COM object in a thread created for that purpose so it will get a different apartment.
A WPF application actually runs just fine with multiple UI threads, as long as each UI thread has manages its own part of the UI, and the parts are separated by HwndSource. In other words, the second thread that runs part of the UI implements a Win32 HWND which is then embedded in the portion of the UI run by the main thread.
If your COM object isn't itself a GUI object, then it should be very easy to construct it in a separate worker thread and leave it there. Since it is a STA object, all calls will be marshaled to the other thread.
BeginInvoke is still going to execute your call on the same thread, just asynchronously*. You can either create a new Thread object:
Thread comthread = new Thread(new ThreadStart(delegate() { DoSomeWork(); }));
comthread.Start();
or try out .Net 4's new Task library:
Task.Factory.StartNew(() =>
{
DoSomeWork();
});
which are essentially the same thing.**
*A delegate type's BeginInvoke method executes on the same thread as the caller, but in the background. I'm not sure if there are rules regarding what gets executed when, but it's certainly not in the order you want. However, asynchronous methods like BeginRead execute on a special thread separate from the main one.
**There is a slight difference - the Thread method will always create a new Thread object, whereas the Task system has a pool of threads to work with, which is in theory more efficient.
I have done some more thinking and testing about this. There is nothing wrong with the C# code. If the ATL object is an STA object (as it was in my case), it will be called on the main thread, regardless of attempts by the C# code to call it on a worker thread. Changing the ATL object to an MTA object makes it possible to to call it asynchronously.