I am writing a small test application to test a communication interface. The communication interface is written in C++ (a DLL) and the test application using C#. The communication interface in turn talks to a low level hardware stack which uses windows messages to transmit and receive data. In order to achieve this, the commuication interface DLL creates an invisible child window whose parent is the C# test application window. The sequence to talk to the hardware is as follows :
Initialize the communication library. This step expects the main window handle and application instance which is passed to the low level stack for windows messaging.
Connect using the device address
Read/Write
Close
Deinitialize the communication library.
Now in the 2nd step, the DLL creates an invisible window to communicate with the low level hardware stack. Since the 2nd step is a blocking call, I want my UI to be responsive during this time in case it takes a long time to connect. Therefore, I try to connect asynchronously using a thread or a BeginInvoke call. But I observe that after the connection is established, the application window hangs as long as the child window exists. The child window seems to block all incoming messages to the main window. This seems to be because the child window gets created in another thread.
But I dont want want the connect to be in the main thread as it hangs the UI.
I would welcome any ideas on how to avoid this problem ? Thanks in advance.
-Harish
All communication with a window handle must be done on the thread this handle was created on. This probably means that all calls to the DLL should be done on the secondary thread.
You can try the following:
Before initializing the DLL, start a background thread;
On that thread, create a WinForms window you do not show. You can do this like this:
-
public static Form BackgroundForm;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
new Thread(new ThreadStart(Secondary)).Start();
Application.Run(new MainForm());
}
static void Secondary()
{
BackgroundForm = new Form();
// Calling Handle creates the system HWND. You do not have to call Show
// or something similar on this Form to make the handle available or use
// Invoke or BeginInvoke.
var handle = BackgroundForm.Handle;
// Initialize the DLL here with the handle.
Application.Run();
// Unintialize the DLL.
}
Then, initialize the DLL with the handle you got from the background form;
When you need to do calls to the DLL, do this using Invoke and BeginInvoke to this background form;
Once it's time to shut down your application, do an Application.ExitThread() through a Invoke or BeginInvoke.
The problem you are seeing with the main form being blocked, is probably because the child window created in the DLL has the main form's handle as it's parent Window, but that's just a guess. This should probably also be solved using this system.
Related
Two windows apps communicate through .net remoting. The host publishes an instance of a class that the client can call methods on through remoting.
The class has a method which pops up a form if not already visible, using form.Show() and performs some functions in a thread.
When the thread completes the form disappears even though I don't explicitely close it. The instance of the class does not go out of scope, and the class instance maintains a reference to the form.
I don't want the form to disappear and am thinking that if I use the Form.Show(System.Windows.Forms.IWin32Window) overload this would work if I pass the applcation main form to the Show method. The problem is my class instance knows nothing about the application. Is there any way to find the applications main form?
The form is being created and shown inside the thread.
I have a c# form application. when this form is closed from task-manager's process i have to do something in my Form application. is it possible?
I apologies if i mislead anything. but i need this solution.
No you can not. What you can do, in order to track this kind of situation, is on startup create some hidden file in directory where you guaranteed by the OS for write permit and on the close of your application, delete that file.
In this way, if on startup of your app, you will find hidden file, that will mean that application was closed non in normal way. So you can execute some actions accordingly.
Hope this helps.
The task manager will try to close your application gracefully first. You will get a normal close signal that you can act on. In a Forms Application that probably corresponds to the OnClose/Closing of the main window. If this signal is not used to end the application in time, the task manager will kill the process. You will not be able to intercept that or act upon it.
Based on what I know, Killing a process with Task Manager is immediate.
The application is not able to get informed in any way.
Task manager generally call the Windows API ExitProcess to kill the process.
On how to hook API, you can refer to:
http://www.codeproject.com/KB/system/hooksys.aspx
SOURCE
In alternatve, you could create an additional process which obsverve the main application and if he find that the application is closed then do something. If the main application is closed normally, then the process is killed from the main application. thiS could be an easy workaround.
"No you can't, what you can do though is do something just before the form is disposed. msdn.microsoft.com/en-us/library/…. What exactly are you trying to archieve? –"
UPDATE
Based on your response to my comment:
What if you do something else. Create a windows service (daemon) that checks when your form is open (windows name) and then monitors the form to check when it is closed, and when that happens it calls the web service you need.
Your windows service would be as simple as this:
Thread thread = new Thread(() =>
{
while (!formClosed)
{
if (!Process.GetProcesses().Any(x => x.MainWindow.Title.Contains(windowName)))
{
//form closed, call your web service
}
Thread.Sleep(5000);
}
});
Using the CoreScanner Driver provided by Motorola, I'm trying to write a small winforms application that uses a barcode scanner. I'm able to interact with the scanner just fine, and properly register a call back for the OnBarcodeEvent(). In this callback, I have a Dialog that opens and displays a screen that the user needs to fill in. Shortly after the dialog is opened (using Show()), the program hangs. If I use ShowDialog(), the dialog works, but the dialog is blocking the OnBarcodeEvent event.
My guess to what is happening, is that since the dialog is getting created on the event thread, there is a race condition occurring when using Show(). Since Show() is non-blocking, the thread continues on after displaying the dialog and then dies out. Meanwhile my dialog just lost it's parent and locks up? Like i said... my best guess.
How can I remedy the situation? That is, How do I write my dialog so that it can be created within a thread not hang?
In the event, you should launch a different thread that will create your dialog form and show the form on it. You need to block this thread till form is visible - this is possible either by ShowDialog or alternately use one of Application.Run overload.
Yet another option would be to show the form on the UI thread (i.e. main application thread) - to do that, you need to call Invoke method on your main form from the event code. The invoke call should take the delegate that will show your dialog form non modally.
I have some experience with Motorola/Symbol Handheld-Devices (MC9090) and I guess the SDK will be similar.
It's hard to say without seeing the code, but my guesses:
your common not-UI thread problem - so make sure you open your dialog using UI thread
the native Motorola-driver is crashing - no kidding, this happened a lot to me - in my case (compact-framework on a WinCE device) this would not freeze the program but the scanner will not work/receive any messages before restarting the device
In order to fix this you should seperate the showing/handling of user-dialog away from the event and make sure you call this on the UI-thread (Control.InvokeRequired / Control.Invoke).
On a Windows CE application, I'm using Application.Exit() for closing the application but one of the dll's that I use isn't disposed and causing me problem when I try to re run the application.
Is this because Application.Exit() doesn't dispose it or I'm still using it somewhere?
What is the correct way to close an application?
Thank you
Edit: Ok to give more details, Here is my scenario:
Main page -> Lets call this A
Idle page -> Lets call this B
Page that closes the app -> Lets call this C
On app.start, A opens B and B opens C with the help of a thread, this is why I'm using application.Exit(). Maybe I should go to parent.parent.parent and call close() on main form? :)
Normally closing the main form is chosen way to leave an application. Application.Exit was historically a less preferred way as it semi-implied more drastic shutdown as some of the close events are not triggered (such as mainform.close etc)
In a typical application the Application.Exit call will only cause the main thread to shut down. Background threads, particularly non-ui ones, will not be terminated via this call. If any are left running the process will continue.
This could very well be the reason you still see resources being held after calling Application.Exit. One way to quickly verify is to see if the process is still running after Application.Exit runs. If so then this is almost certainly your problem.
I am optimizing the startup of a WinForms app. One issue I identified is the loading of the splash screen form. It takes about half a second to a second.
I know that multi-threading is a no-no on UI pieces, however, seeing how the splash screen is a fairly autonomous piece of the application, is it possible to somehow mitigate its performance hit by throwing it one some other thread (perhaps in the way Chrome does it), so that the important pieces of the application can actually get going.
The .NET framework already has very good support for splash screens in Windows Forms apps. Check this thread for a code sample. It is indeed optimized for warm startup time, it makes sure the splash thread and screen is up and running before initializing the main app.
There's nothing to be gained from spawning a thread if your goal is to get the splash screen up as quickly as possible.
There are several ways to do splash screens, and a more sophisticated one is mentioned here, but this is an easy method I have used with complete success:
Just ensure you load and show the splash form first, and then continue to load your app while the user is looking at the pretty splash screen. When the mainform is done loading, it can close the splash right before it shows itself (a simple way to do this is pass the splash form to the mainform in its constructor):
static void Main()
{
Application.SetCompatibleTextRenderingDefault(false);
SplashForm splash = new SplashForm();
splash.Show();
splash.Refresh(); // make sure the splash draws itself properly
Application.EnableVisualStyles();
Application.Run(new MainForm(splash));
}
public partial class MainForm : Form
{
SplashForm _splash;
public MainForm(SplashForm splash)
{
_splash = splash;
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// or do all expensive loading here (or in the constructor if you prefer)
_splash.Close();
}
}
Alternative: If you prefer not to pass the splash to the MainForm (maybe it seems inelegant), then subscribe to the MainForm's Load event, and close the splash screen there:
static class Program
{
static SplashForm _splash;
[STAThread]
static void Main()
{
Application.SetCompatibleTextRenderingDefault(false);
_splash = new SplashForm();
_splash.Show();
_splash.Refresh();
Application.EnableVisualStyles();
MainForm mainForm = new MainForm();
mainForm.Load += new EventHandler(mainForm_Load);
Application.Run(mainForm);
}
static void mainForm_Load(object sender, EventArgs e)
{
_splash.Dispose();
}
}
As mentioned in this thread, the potential downside to this solution is that the user won't be able to interact with the splash screen. However, that usually isn't required.
Multithreading in WinForms is okay as long as all the UI stays on one thread.
This is just how splash screens are usually done. The important work is done on a background thread, while the splash screen window is shown on the UI thread to let the user know that the rest of the program will appear soon.
After the important stuff has happened, raise an event to let the UI thread know that it is time to hide the splash screen (just remember to marshal the event handler, using Invoke(), back onto the UI thread in order to close the splash screen).
Yes.
You need to make a new STA thread that shows the splash screen using Application.Run, then call Close using Invoke after the main form is ready (on the main thread).
EDIT: For example:
static SplashForm splash;
Thread splashThread = new Thread(delegate() {
splash = new SplashForm();
Application.Run(splash); //Blocking call on separate thread
});
splashThread.SetApartmentState(ApartmentState.STA)
splashThread.Start();
LoadApp();
//In MainForm_Shown:
splash.BeginInvoke(new Action(splash.Close));
For optimal performance, you should make your Main method show the splash screen, then call a separate method that loads the application. This way, all of the assemblies will be loaded after the splash screen is shown. (When you call a method, the JITter will load all of the types that it uses before the method starts executing)
The answer is really about perception. There are various methods, NGEN an assembly, putting things in the GAC, but what you should understand is what is really going on.
C# require time to load the virtual machine, load referenced assemblies, and load assemblies based upon what is on that splash screen. And then it still takes awhile from a "cold" start to launch the first screen.
This is because of the JIT compiling that is going on when you first access a screen.
A strategy that I use is a traditional lightweight splash page that loads quickly so its visible, but in the background I spawn a thread and load an invisible form. This form has all the controls that I intend to use and so the JIT compiler is doing its thing and its loading the assemblies. This provides the illusion of responsiveness with slight of hand. The time it takes from launch + visible splash page + pause + time to click 1st option is greater then the time it takes for the thread to execute and then cleanup and unload the form.
Otherwise, applications appear to be clunky and slow for users when it first starts. Warm startup of screens is much faster because the assemblies and JIT has finished.
We do it by providing a tiny small native C++ application that serves as the splash screen.
It then follows this process:
User double clicks the application icon.
The C++ app starts, showing a splash bitmap as WS_TOPMOST.
The C++ app launches the main C# app.
The C# app starts, finally notifying the C++ app (through a simple file) to quit.
The C++ app quits.
The C++ application also has a timeout (in case the C# app crashes) and quits automatically if it does not get notified to quit within 30 seconds.
This approach has its drawbacks in the fact that you cannot pin the application to the task bar. If you pin the C++ app (which is the main app for the end user), you get another task on the task bar, because the C# app is different. I think, I could solve this by providing settings in the application manifest of both the C++ and C# application to instruct them to be the "same" application in terms of the task bar.