I have a big winform application that takes long time to load so I wrote a splash screen for it.
The problem is that when I show the splash form from a new thread, the progress bar will freeze 2 or 3 times while loading. But when I do it using a separated process I haven't any problem and it has a smooth motion.
I want to know that what's the difference between a new thread and a separated process in such a situation.
Thanks
Simply think of it as the Main form has it's own thread. When you are doing something on that thread that is task intensive, it doesn't get a chance to update the UI. However, when you create a new thread, you are in effect creating a new worker that can update the splash screen UI, while the Main form's thread is performing its workload.
A process is an executing instance of an application. For example, when you double-click the Microsoft Word icon, you start a process that runs Word. A thread is a path of execution within a process. Also, a process can contain multiple threads. When you start Word, the operating system creates a process and begins executing the primary thread of that process.
Another difference between a thread and a process is that threads within the same process share the same address space, whereas different processes do not.
It could be because the UI for the splash screen needs to be in a completely separate thread from the main window with a totally separate Windows message queue.
To run some UI in a different thread from the main thread you will need to start a new message pump for it, because message queues cannot be shared between threads.
To start a new message pump, call Application.Run(yourSplashScreen); from the separate thread. Create your splash screen form from the separate thread too.
Note that you cannot directly manipulate controls in one form from code executing in a different form that you started in a separate thread. You would have to use Control.Invoke() to do so, just like you normally do with multiple threads.
Anyway, if you use a separate message queue like this it could help to prevent the stalling that you're seeing.
Related
I have a WPF application in which I have a MainWindow under UI thread. I have created a thread in which I create another window. I have to create this window in a thread because it has to be updated continuously. I want the owner of this window to be the MainWindow. So I am using Dispatcher.Invoke to set the owner of this window.
But when I use Dispatcher.Invoke to access Main UI Thread from Thread 2, I get a cross thread access exception.
I'll post some sample code very soon. Until then, if someone has any idea, please share it.
This is my actual problem to which I thought of implementing above mentioned approach:
I have three line charts with 4 line series each in a window which are updated at an interval of 100 ms which I am doing using Dispatcher.Invoke. Because of this, the UI becomes kind of slow and unresponsive sometimes
I have created a thread in which I create another window.
That already isn't a very good idea and is prone to a lot of problems. All windows in your application should be created by the main "GUI" thread.
I have to create this window in a thread because it has to be updated continuously.
There are ways to achieve that without creating the window on another thread. Create your window on the main thread, then use a background thread to update it. That background thread can update your new window by using Dispatcher.Invoke.
In my application there is a ListView with files and folders. User can load them on server. Loading is performing in separate thread but I show the state of the process in a progress bar on the Form, using Control.Invoke(ShowProgressMethod... method, so ShowProgressMethod is called on the Main thread.
Everything works fine, but when I try to do something else in the Main thread (for example delete one file), the UI is blocked. It is usually happend when process is refreshed in ShowProgressMethod and during this I called another method from the same thread.
How can I fix this?
I have a very complex Window created with WPF.
Since it takes very long time to load (about 10s), I want to create the window in the background after startup of the application.
My Shell contains one button where this window will be used, when the User clicks on it. The idea is to load the application and this button is disabled. After loading, my complex will be created in the background. When the window is created, I can enable this button and the user can use it.
But it is very important, that the Application does not block, while the window will be created on the background. The user should be able to use other modules in this time.
Does somebody know a way to reach my goal?
Perhaps someone knows, if there are more possibilities to reach this goal in the next .NET-Framework 4.5?
You can create window in background thread. Things you need to pay attention to are:
Thread must be STA and should be background thread so it will be terminated if main application thread is terminated.
You must keep that background thread alive or you will loose your window.
When referencing other GUI elements you should use Dispatcher.Invoke or Dispatcher.BeginInvoke if that GUI element is from another thread.
Here's the example for creating window in background thread:
Thread thread = new Thread(() =>
{
Window windowInAnotherThread = new Window();
windowInAnotherThread.Show();
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true };
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Use the BackgroundWorker.
Note that you can not create the actual window in the BackgroundWorker. The window needs to be created on the UI thread. But you can load all necessary data in the BackgroundWorker and use that data from the form once it is loaded.
when my program in any process (load csv file for example)
i see 'program Not Responding' and i see black screen - in Windows-7
in Windows-XP i dont see it
(after this the program Continues normal)
Why is this happening ?
When a long process is running, if it's running on the UI thread, that causes the application to not respond to other UI events, most notably drawing the screen. In both Windows XP and Windows 7, this will cause application to be reported as "not responding", but XP and Windows 7 handle window painting differently.
In XP, the application actually updates the screen, but in windows 7, the OS saves what the current screen looks like, then displays that on the screen using a different mechanism (for example, with Aero enabled, it actually displays the contents of the windows using textures in pseudo-3D).
In 7, this can cause applications that are not responding to display black (or the last-known screen in faded grey, depending on graphics settings) screens (because it doesn't have any up to date information). Whereas in XP, it leaves the old content up, but dragging a window over it causes shadows of the window to be displayed on the screen, because the lower window is not updating.
Update:
How do you fix it? Well, there's a bunch of different things, but if you have a method that takes a very long time:
private void SomethingThatTakesAReallyLongTime()
{
System.Threading.Thread.Sleep(30000);
}
Your event handler can look like this:
private void button1_Click(object sender, EventArgs e)
{
((Action)SomethingThatTakesAReallyLongTime).BeginInvoke(null);
}
This may not be a good idea in many cases, but it's a simple example of things you can try.
You are tying up the UI thread (main thread) for an extended period of time likely because the operation is intensive (either CPU or disk). Try moving the intensive operation (say reading file) into a second thread. This will keep the main thread (one w/ UI) responsive to the user and OS.
There are numerous methods to accomplish this. Using a BackgroundWorker is the simplest to implement. This should get you started:
http://msdn.microsoft.com/en-us/library/cc221403(VS.95).aspxr
Esesentially you will:
Create a backgroundWorker
Create an event handler for the DoWork event and wire it to DoWork.
Place the CPU intensive operation inside the DoWork event handler.
Call the RunAsync() method of the backgroundWorker (which will keep off DoWork event)
You can get more complex with providing progress and allowing user to cancel. Here is an example of loading large file:
http://msdn.microsoft.com/en-us/library/ms229675.aspx
This happens when your main thread is working on a relatively long-running task and therefore cannot repaint the screen. Thy using a worker thread to load the csv (for this example) and you shouldn't have this problem.
More than likely, it's happening because you're trying to execute a long running process on the UI thread (which blocks the UI thread so that it can't redraw the form).
You should use some form of Threading to start the long running process on a separate thread so that the UI can continue to function.
My winforms app isn't shutting down nicely when I log off/shutdown. I have a main form, whose Closing event is fired correctly, but there must be something else keeping my application around. If I check Application.OpenForms there's just my one main form.
The tricky bit, and where the problem probably lies, is that my application uses ShellWindows to hook into Internet Explorer, and occassionally opens up forms when IE events fire. It's after one or more of these forms has been opened and closed that my app stops closing on shutdown.
I think I'm cleaning up all form objects etc and calling FinalReleaseComObject() appropriately, but I guess there are references somewhere that are holding my process open. Is there any way to work out what it is that's stopping my app from closing gracefully?
An application will also stay open if there are threads running that have not been set to background. If you are creating any of your own threads, make sure that they are terminating appropriately.
If it is not critical that the thread finishes, set IsBackground to true. You can also call Abort on a thread to (somewhat)forcibly kill it.
The most likely cause is that you have a background thread hanging around that is not being closed when the main window of your application is closed. Depending on your settings and framework version background threads can keep an application alive when the main thread is terminated.
During shutdown windows asks every running app to terminate usually by sending a WM_QUIT to the main window on a process. WinForms will happily use this message to shutdown the main window but if any background threads are left the actual process could continue.
This is a really ugly way to do this, but if all you want to do is kill any thread that's hanging around, you can get all the threads running in your application with System.Diagnostics.Process.GetCurrentProcess.Threads, and then enumerate through them and call Thread.Join() or Thread.Abort() on them.
Just make sure to NOT call .Abort() on the main (UI) thread that you're working from (the one that receives the Closing event). So make sure to check that your current thread (System.Threading.Thread) is not the one you're aborting.