Wait for WPF app to load after starting with Process.Start() - wpf

I have a WinForms app that starts a wpf process running using Process.Start. I would like to know when the WPF process is finished loading and I can access the process.MainWindowHandle property (its 0 before its completly loaded).
I tried polling but the handle is always 0. However, if I debug and wait (after Process.Start) for the WPF app to load - I then will get the correct handle.
Does not work:
int maxCount=100000;
int count=0;
do
{
wpfProcess.WaitForInputIdle();
_hWnd = net4ReconProcess.MainWindowHandle;
count++;
} while (_hWnd.ToInt32() == 0 || count > maxCount);

Add process.Refresh(); to the while loop.

Using a while loop for WaitForInputIdle is a non-sense because this call blocks the current thread until the other process has finished its initialization. After that, it always returns immediately. Please read the post WaitForInputIdle should really be called WaitForProcessStartupComplete – The Old New Thing
As raymond says it, it should really be called WaitForProcessStartupComplete.
You should use this code:
if (!wpfProcess.WaitForInputIdle(10000)) // 10 s timout
throw new ApplicationException("Process takes too much time to start");
_hWnd = net4ReconProcess.MainWindowHandle;

Related

WPF application continues even after explicit shutdown

I have a simple wpf application that continues to run even after I explicitly call it to shut down.
It integrates with a third party application and needs to check that a few documents of a certain type and with specific content are open as it initializes.
Here is a portion of the initialization code:
try
{
ActiveProductDoc = Automation.CATIA.ActiveDocument as ProductDocument;
}
catch
{
InvalidAssemblyShutdown("You must have an assembly open before you run the app");
}
if(ActiveProduct == null)
InvalidAssemblyShutdown("You must have one assembly open (not a part)");
ActiveProduct = ActiveProductDoc.Product;
And here is the InvalidAssemblyShutdown method:
private void InvalidAssemblyShutdown(string message)
{
MessageBox.Show(message);
Close();
Application.Current.Shutdown();
}
I have set the application's ShutdownMode property to OnMainWindowClose.
I am currently doing a use case test where the user has the wrong type of document open and so the ActiveProduct field is null. The InvalidAssemblyShutdown method is called as expected but despite this the line in the initialization method following the shutdown call still runs and throws an exception.
Any ideas what's going on?
Should I throw exceptions instead and use a global exception handler?
If you have a look at the source code for Application.Current.Shutdown (link to source), you'll see that it uses Dispatcher.BeginInvoke() to initiate the shutdown. In other words, the shutdown gets queued on the UI thread. It doesn't take effect during that precise method call, so the following code keeps executing.
You'll need to exit the code right after the call to Application.Current.Shutdown if you don't want some code to run while the shutdown request gets processed. Something like:
if(ActiveProduct == null)
{
InvalidAssemblyShutdown("You must have one assembly open (not a part)");
return; // prevent further code execution.
}
For what it's worth, this.Close() works in a similar way. So if you have proper flow control, you won't need to invoke Application.Current.Shutdown at all. Your call to this.Close() should be enough.

Display progress in a long loop in Unity3d

I'm building a space game, populated by thousands of star systems. Right now, there is a function that generates these thousands of systems. It takes about 5-10 seconds to generate, and I would like to have a simple progress bar updating the user in the progress.
After some searching I've decided to use a coroutine, however there is a little problem: when I call the function to generate star systems, the code that called the function keeps on going, reporting zero stars (because they haven't been generated yet).
I have a feeling coroutines are not an answer for me. Basically, I am simply looking for a way to simulate Application.DoEvents to update the GUI.
Here is a sample of my code:
// Start generating thousands of systems
StartCoroutine(GalacticMap.GenerateRandomGalaxy());
// after the universe is generated...
Game.myGalaxy.StarSystems = GalacticMap.myGalaxy.StarSystems;
// report back the number of systems
print(String.Format("Generated {0} systems", Game.myGalaxy.StarSystems.Count));
In the GalacticMap.GenerateRandomGalaxy() I am yielding back like this yield return new WaitForSeconds(0.1f); however, the effect is not what I am looking for: execution goes right through to print statement while the generation is still on going.
So how do I do this?
EDIT 1:
I've cooked up a sample code to illustrate my issue.
The caller code:
Debug.Log ("Start generating");
StartCoroutine(GenerateMeGalaxy());
Debug.Log ("Finish generating");
The code I call:
public static IEnumerator GenerateMeGalaxy ()
{
Debug.Log ("GenerateMeGalaxy start");
int numberOfStars = 1000;
for (int i=0;i<=numberOfStars;i++)
{
// generate galaxy
// display progress bar on screen
Debug.Monitor(String.Format("{0}% completed", ((i*100)/numberOfStars)),2);
yield return new WaitForSeconds(0.001f);
}
Debug.Log ("GenerateMeGalaxy end");
}
In the code above, Debug.Log displays string on the screen, on a new line so you can read previous logged strings of whatever. This is to debug code execution. Debug.Monitor has a fixed location on the screen and will overwrite previous string. This is where I display progress percentage. What I see after running this code is:
Start generating
GenerateMeGalaxy start
Finish generating
GenerateMeGalaxy end
What I want to see is:
Start generating
GenerateMeGalaxy start
GenerateMeGalaxy end
Finish generating
... and also the progress update is happening in between:
GenerateMeGalaxy start
Finish generating
I think you are misunderstanding how Unity coroutines work. What the yield return new WaitForSeconds(0.1f) is essentially saying is "go do other stuff and come back to me after 0.1 second". So naturally Unity will go ahead and do other stuff, including the print statement.
What you want is something along the lines of the following pattern:
IEnumerator GenerateRandomGalaxy()
{
int numSystems = 5000; // however many systems you want to generate
foreach(int i = 0; i < numSystems; i++)
{
// insert code here that generates system i
// insert code here that updates the progress bar
yield return null;
}
// put logic that prints out final number of systems generated here
}
What this does is generate a system, update the status bar, and then -- with the yield return null statement -- tell Unity to take over (so that it do other stuff, including rendering the updated progress bar) and come back and continue the loop as soon as possible.
Finally, the print statement only happens after the loop is finished, as you intend.

Calling thread cannot access object because different thread owns it

I thought I knew what causes this exception until I wrote this:
var menu = ViewConfigHelper.CreateObjectFromResource<Menu>(config, baseURI);
if (!menu.Dispatcher.CheckAccess())
{
throw new ArgumentException("Somethign wrong");
}
if (!LayoutRoot.Dispatcher.CheckAccess())
{
throw new ArgumentException("SOmethign wrong");
}
// exception throw here
LayoutRoot.Children.Insert(0, menu);
First line creates a Menu control from an embedded XAML file. Both CheckAccess calls return true. However, when last line is executed, an exception is thrown with the message "Caling thread cannot access object because differrent thread owns it." The code above is being executed within a method called immediately after InitializeComponent() that created LayoutRoot, on the same thread, I believe.
Someone please enlighten me. I am trying to create a multiple UI thread WPF app.
You are using CheckAccess() in reverse. You want to lose the ! signs before each check. See the example bit of code on the CheckAccess() MSDN page.
In the Winforms world you'd do a InvokeRequired() which is now the same thing as a !CheckAccess(). In your case because both values are returning true, and you are inverting them, neither if block is hit.
To expand a bit... in the Winforms world, the normal patter was:
if(InvokeRequired)
{
Invoke(...);
}
else
{
//do work
}
(or sometimes a return after invoke, if it was invoking the same method).
In WPF, CheckAccess() is similar to, but not identical to InvokeRequired... there for a pattern more along the lines of:
if (someUiControl.Dispatcher.CheckAccess())
{
//Doing an update from this thread is safe, so we can do so here.
}
else
{
// This thread does not have access to the UI thread.
// Call the update thread via a Dispatcher.BeginInvoke() call.
}
The key difference between is that InvokeRequired() returning true meant it was UNSAFE to do the update in the current thread... while a true from CheckAccess() means it is SAFE.

Show window with progressbar while doing work

Because I have a tool that needs to do a lot of work at one point, I want to show a window with some text and a progressbar while doing the work.
My problem is, that because of the huge load of the work, the window never gets drawn or updated.
I know that I usually should use an extra thread for the work, but I have to use 2 collections and the database service from the current thread.
The current code is something like
StatusWindow SW = new StatusWindow();
StatusViewModel SVM = new StatusViewModel();
SVM.MaxNum = BigNumber;
SW.Show();
for (int i=0; i<BigNumber; i++)
{
List<AType> ItemsToCreate = Func1();
List<AType> ItemsToDelete = Func2();
foreach (AType cItem in ItemsToCreate)
DB.CreateItem(cItem);
foreach (AType cItem in ItemsToDelete)
DB:DeleteItem(cItem);
SVM.CurrentNum = i;
}
SW.Close();
I also read about the Dispatcher, but i don't think it is very usable in this scenario, since there would be too much access to the main thread.
Any suggestions?
Thanks
I recommend reading the article (Build More Responsive Apps With The Dispatcher) from MSDN magazine that describes how WPF works with the Dispatcher when using BackgroundWorker.
You can pass the two collections and whatever else you'd like to worker threads as long as the objects you are accessing can be accessed from different threads.
int[] arrayofInt = new int[10]
ThreadPool.QueueUserWorkItem(s =>
{
//access the array in the worker thread
arrayofInt[0] = 10;
});
When finished with the work, you need to send a message to the dialog that it should be closed now. Do that by firing an event in your thread that is handled by your dialog.

Application.Current.Shutdown() doesn't

Title's about it. WPF app with some WCF stuff for IPC. I call Application.Current.Shutdown() and the app continues on happily. I thought Shutdown was supposed to be unstoppable.
Perhaps because it's being called from a background thread? Do I need to do some dispatcher fiddling?
You get an exception when I call Application.Current.Shutdown in any thread other than the main one, so I'd assume you where using "dispatcher fiddling" properly already.
In any case, this compiles and quits an application, so if the dispatcher bit doesn't look like what you have you could sling it in:
ThreadStart ts = delegate()
{
Dispatcher.BeginInvoke((Action)delegate()
{
Application.Current.Shutdown();
});
};
Thread t = new Thread(ts);
t.Start();
In my experience all threads have to either be terminated explicitly or be marked as background threads in order for the application to close.
Here is an example of kicking off a read thread in the background:
_readThread = new Thread(new ThreadStart(ReadThread));
_readThread.Name = "Receiver";
_readThread.Priority = ThreadPriority.Highest;
_readThread.IsBackground = true;
_readThread.Start();
The IsBackground property is the key. Without that being set, the thread won't terminate on when you call Shutdown.
I only experience Application.Current.Shutdown not working when I'm running from Visual Studio. Within Visual Studio (at least the 2010 version I'm using) Application.Current.Shutdown doesn't do a thing. If I single step through it executes this line and then continues. If I run the program (as an .exe) from Windows Explorer then Application.Current.Shutdown works fine.
There is probably an explanation for this since during debug other threads are active, but I can't explain it.

Resources