this might sound dumb, I am new in WPF and in my application I open an additional window using Task.Factory.StartNew because the function runs in separate thread. After the debugging stops, this window stays open but without any images, only the text/clicking/animations are shown, but through this I can open other windows, as if the software was still running, which actually does through a process called "WPFSurface.exe", I assume it's some sort of debugging or just a bug but I can't find any information on google or stackoverflow. Here's the code that I use to create the window:
Task.Factory.StartNew(() =>
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
var controls = new ScreenControls(display);
controls.Show();
}));
});
I also close the application using this code (Yes it's binded correctly to Closed event)
private void MainWindow1_Closed(object sender, EventArgs e)
{
Application.Current.Shutdown();
}
Thank you for your time!
Related
I have a simple wpf application. But it is using CefSharp to open some links in chrome based browser. I found that once the main window of the application is closed, It is closed from the UI but it still runs in the background.
I tried adding additional code to force close it. but no hope. I think some components of cefsharp is not ending correctly. but not exactly sure on what is going wrong.
Used the below code and some other snippets too
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
foreach (Window w in App.Current.Windows)
{
if (w.DataContext != this)
w.Close();
}
Application.Current.Shutdown();
}
As I said in my comment, try: Environment.Exit(0);
If that doesn't work, start with Cef.Shutdown();
https://stackoverflow.com/a/9050477/1274820
If you REALLY need it to close out you can also use Environment.Exit() but it is not graceful at all (more like ending the process).
We are using NUnit to test a WPF control.
The text fixture basically opens a test window containing the control to be tested on a new thread. Then the Microsoft UI Automation (UIA) is used to interact with the control.
The new thread shows the window and starts the dispatcher. Things work as expected.
The issue we are running into is that this control can launch a dialog. Once the dialog is launched we need to interact with it and close it. I have been unable to get a reference to this dialog to accomplish this task.
One solution that does not work is to use Application.Current.Windows to get all the windows and then iterate through them until the dialog is found. This does not work because during unit testing Application.Current = null. Now if we only care about this test we can just instantiate an Application. This will however interfere with other tests, because the Application will automatically enter shutting down mode when our Application variable goes out of scope (at the end of the test). As a result other tests will fail (most notably because InitializeComponent typically calls System.Windows.Application.LoadComponent which can't be called during shutting down mode).
I suppose what we need is an alternative to Application.Current.Windows.
I found a working solution to my problem.
UIA fires a number of events. One of them indicates that a new window has opened.
Subscribe a handler to the WindowOpenedEvent:
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, new AutomationEventHandler(NewWindowHandler));
public void NewWindowHandler(Object sender, AutomationEventArgs e)
{
AutomationElement element = (AutomationElement)sender;
if (element.Current.Name == "PUT YOUR NAME HERE")
{
HwndSource hSource = HwndSource.FromHwnd(new IntPtr(element.Current.NativeWindowHandle));
MyWindow = hSource.RootVisual as WavefrontToolkit.FormulaEditor.FormulaEditor;
Assert.IsNotNull(_MyWindow );
}
}
}
In the handler you do not have a reference to the window that was opened. You can however get it from the Win32 handle.
The other issue I encountered is that the test will continue on as the Window is opening. Some of the test might be depended on that window. To deal with that I cause a delay until the Window is ready.
while (MyWindow == null)
{
System.Threading.Thread.Sleep(10);
}
I have a project that I'm doing with
Microsoft VSTO (office 2013 excel)
I have certain things that make calls that take maybe 10 seconds to come back.
Ideally I would like to display an progress bar or some status... After a lot of searching I found an article that is titled:
How do I create a splash screen window for the VSTO applications?
http://www.datazx.cn/Fv7p5a/xw/oa2v/2q7xs6/mcccjfti-988m-f8r8-8d44-bstb4rfsi4xm23rsdfd.html
So I started creating this code in a form, but then I realize that I need to call it up within my methods and really attach events etc...
The article says to
"display a modal form on a background thread" What is the best way to do this?
I find it easier to use modal less form on main thread and so far haven't seen any problem with modal less approach. Something like code below
var splashWindow = new SplashWindow();
splashWindow.Show();
splashWindow.SetMessage("Starting please wait...");
DoSomeWork(splashWindow);
splashWindow.Close();
Following you will see a way I programmed a Splash Screen for Excel-VSTO in C#. My Excel file is enabled for macros (.xlsm). These are the steps:
Create your splash screen. Let's assume the name of the form is SplashScreen.
Go to the code of the object ThisWorkbook.cs
Check the code looks like:
public partial class ThisWorkbook
{
SplashScreen SC = new SplashScreen();
private async void ThisWorkbook_Startup(object sender, System.EventArgs e)
{
SC.Show();
await Task.Delay(3500);
SC.Close();
more code...
}
}
It is important that you notice that I added the word async to the subroutine.
private void ThisWorkbook_Startup(object sender, System.EventArgs e)
I hope this is very useful.
I am working with a team on an application that has a report generator and then a report viewer. At the moment we have not been able to open up the report viewer in a separate thread. These two applications should be independent once opened, and if one is closed it should not effect the other.
The Report Viewer has one UI set of files and the main UI has another set. My question is how can we open up the Viewer UI in a separate thread once the main UI is back in it's "idle" state (not hidden, just not processing anything)?
Any short code snippets would be helpful, at this point I am completely lost on how to open up the viewer in a new thread...
Perhaps something along the lines of this:
private void MethodName {
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ThreadProc));
t.Start();
}
and the ThreadProc code will look like this:
public static void ThreadProc()
{
Application.Run(new Application_Name());
}
MethodName (for me) is actually
serverToolStripMenuItem_Click(object sender, EventArgs e)
As it is an event-driven code.
Application_Name will be the form or Application you want to run.
Hope this helps.
I have a options window and a window that displays color based on these options and Kinect data. So far everything's on one thread (as far as I know; I haven't done any threading).
Now, I'm adding an option to open a viewer window that will need to be updated with lowest possible latency. All this entails is creating a window and showing it:
viewer = new SkeletalViewer.MainWindow();
viewer.Show();
When this event fires, the color window stops displaying colors (i.e. the event that fires 30 times a second on the main thread stops firing), but the viewer is displayed perfectly. I want the viewer and the color window to both be updated.
From reading other questions, it sounds like the solution is to create the viewer on a new thread. I'm encountering a lot of problems with this, though.
This fires when I click the button to open the viewer:
private void launchViewerThread_Click(object sender, RoutedEventArgs e)
{
Thread viewerThread = new Thread(delegate()
{
viewer = new SkeletalViewer.MainWindow();
viewer.Dispatcher.Invoke(new Action(delegate()
{
viewer.Show();
}));
});
viewerThread.SetApartmentState(ApartmentState.STA); // needs to be STA or throws exception
viewerThread.Start();
}
Regardless of if I just call viewer.Show() or Invoke() it as above, the line throws an exception: Cannot use a DependencyObject that belongs to a different thread than its parent Freezable. Here's how I understand Invoke(): it accesses viewer's dispatcher, which knows what thread the object is running on, and can then call methods from that thread.
Should I be trying to put this viewer on a new thread? Is the problem even a question of threads? The user will not be interacting with the viewer.
Anyone know why this doesn't work? Thanks for the help.
You need to call Show() on the same thread that the window is created on - that's why you are getting the error. Then you also need to start a new Dispatcher instance to get the runtime to manage the window.
private void launchViewerThread_Click(object sender, RoutedEventArgs e)
{
Thread viewerThread = new Thread(delegate()
{
viewer = new SkeletalViewer.MainWindow();
viewer.Show();
System.Windows.Threading.Dispatcher.Run();
});
viewerThread.SetApartmentState(ApartmentState.STA); // needs to be STA or throws exception
viewerThread.Start();
}
See the Multiple Windows/Multiple Threads example at: http://msdn.microsoft.com/en-us/library/ms741870.aspx
So I was running into a similar issue where a new window failed to open on a new thread. The exception was "cannot use a dependencyobject that belongs to a different thread".
The issue ended up being that the window was using a global resource (Background brush). Once I froze the brush resource, the window loaded just fine.
I am not sure if this will solve your problem but can you try creating a thread proc (to open a viewer window) which is executed on a different thread and then have a dispatcher.beginInvoke to update the main window ,
Here is some code-
in the constructor register this
public MainWindow()
{
UpdateColorDelegate += UpdateColorMethod;
}
// delegate and event to update color on mainwindow
public delegate void UpdateColorDelegate(string colorname);
public event UpdateColorDelegate updateMainWindow;
// launches a thread to show viewer
private void launchViewerThread_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(this.ThreadProc);
t.Start();
}
// thread proc
public void ThreadProc()
{
// code for viewer window
...
// if you want to access any main window elements then just call DispatchToMainThread method
DispatchToUiThread(color);
}
//
private void DispatchToUiThread(string color)
{
if (updateMainWindow != null)
{
object[] param = new object[1] { color};
Dispatcher.BeginInvoke(updateMainWindow, param);
}
}
// update the mainwindow control's from this method
private void UpdateColorMethod(string colorName)
{
// change control or do whatever with main window controls
}
With this you can update the main window controls without freezing it, Let me know if you have any questions