I have a C++ application (calling functions of an SDK for a specific hardware component), and want to display its data in a C# GUI. The C# part is a DLL which the C++ calls. (This is by request from the customer so I don't have much choice about it.)
I'm not very well versed in C#, so might be missing something obvious, but I'm running into problems both displaying the GUI and updating it.
I access the C# code using this method, with code roughly like this (ptr is a class variable):
// Initialize COM.
CoInitialize(NULL);
ptr = new IPtr(__uuidof(ManagedClass));
(*ptr)->ShowForm();
then in another thread:
if (updating) (*ptr)->Update(data)
On the C# side we have:
FormClass myForm;
void ShowForm()
{
myForm = new FormClass();
Application.Run(myForm);
}
void Update(Data data)
{
myForm.Update(data)
}
When I use Application.Run or ShowDialog to show my GUI, the form shows nicely but the update makes the application crash. Using Show has the GUI get stuck. Using BeginInvoke resulted in the GUI never appearing.
Is there any recommended way for me to start the GUI given this setup? Would it help to somehow use Invoke/BackgroundWorker in Update rather than calling myForm's method directly?
You must update C# GUI on the the UI thread. See this answer for how to synchronize from another thread to the GUI thread.
C# Windows Forms Application - Updating GUI from another thread AND class?
You might also find the Debug Location toolbar handy to determine what thread you are currently in when debugging in Visual Studio
https://blogs.msdn.microsoft.com/davedev/2012/07/18/where-is-the-suspend-resume-and-terminate-toolbar-in-visual-studio-2012-ultimate/
Related
Currently I have two separate C# projects under the same solution, let's call it Window.exe and Console.exe. Window.exe is a WPF MVVM application that works well standalone.
To eliminate one small issue, my goal is to convert Window.exe into Window.dll, and then use Console.exe to load Window.dll. I tried to call App.Run(), or move the routine in App_Startup, that is used to launch the main window onto a separate method and called it. The new thread that runs Window.dll couldn't really last. It was able to populate the GUI when I stepped into it in debug, but I could not interact with it.
Any ideas on how I should proceed?
I was able to accomplish this by doing two things:
You need to mark the Main method in your console applicaiton as an STAThread method because the UI will need to be on an STA thread. If you don't, you'll get an exception when the constructor for the main window is called.
Make sure you also call InitializeComponent() before Run(). If you don't, the app will run, but the window won't have been set up first.
I was able to get this to work in a solution where I, as well, have a WPF main application and console application for testing things:
[STAThread]
static void Main(string[] args)
{
WpfApp.App app = new WpfApp.App();
app.InitializeComponent();
app.Run();
}
In a simulator I am writing I use SFML and OpenGL to create a visualization with some basic OpenGL based GUI. Now I need to add a File Chooser Dialog. I was wondering if I could use System.Windows.Forms.OpenFileDialog and update it's events dynamically similarly to the way OpenCV allows you to update windows by using cv::waitkey().
Since OpenFileDialog.ShowDialog() does not return until the window is dismissed, all I have to do is somehow close the Dialog by updating it's events.
I would rather not have to call Application.Run() and leave it in the background because my application is already built around a main loop and Application.Run() takes over the main thread.
The equivalent call to cv::waitkey is:
Application.DoEvents()
However after reading Use of Application.DoEvents() it appears that Application.DoEvents() is much more fragile then cv::waitkey. It can cause an application to crash if there is no open win form.
Alternative Approach
I decided to switch to GTK# since it lets you process events as they occur by checking whether any events exist in the event queue by calling Gtk.Application.EventsPending(). Then the events can be processed with Gtk.Application.RunIteration() in a while loop like this:
while (Gtk.Application.EventsPending())
{
Gtk.Application.RunIteration();
}
I am working on an Windows Phone 8 Application that uses mixed C# for UI and C++ for the underlying backed. I have some instances where I need to run some C++ code on the UI dispatcher thread (IE GetGeopositionAsync()).
I have tried a method of making a callback from C++ to C# that runs in the UI thread and then calls a C++ method and runs:
auto window = Windows::UI::Core::CoreWindow::GetForCurrentThread();
However this is returning null. Is there any way for me to accomplish this?
I had a similiar problem some days ago, as it has always returned null. I ended up using in WinRT. According to MSDN (1, 2) you should be able to use this in WP8 as well.
CoreApplication.MainView.CoreWindow
I am creating a video player application with a UI in C# and the video decoding and display (DirectX) in C++.
The C++ code is compiled as a DLL and interfaced with the C# UI.
To maintain the correct display frame rate I need to create a secondary thread either in C++ DLL or C# which can do accurate timing and call the display function at right intervals.
However, creating a secondary thread which posts display to the window created by the primary thread (from C# GUI) creates access violation and results in a crash.
However, if I use a timer object in C# to display, the player works but I am unable to maintain the right frame rate due to it's coarse granularity.
What would be a good solution to handle this?
I think the crashes you experience are caused by the fact that you can't access Windows Forms controls from outside the main thread.
Consider using Control.Invoke() to invoke the execution you need on the main thread.
Bear in mind though that Control.Invoke() uses Windows' message queue to pass the request through, so expect some inaccuracies.
Im running a console app that loads a dll and calls a method from that dll that creates a WPF form. So I'm just calling to Program.Execute() method and it does all the creation of the form. All reflection business goes well, but the form does not appear.
I've been told that this is because a console app does not have a windows message loop, but I'm sure there is a way to simulate that. For example, I tried playing with System.Windows.Threading.DispatcherFrame, but to no avail - the form still does not show up.
Did anyone else face this problem?
Just call WPF's Application.Run(). Or Window.ShowDialog(), same thing. You will also have to apply the [STAThread] attribute on your Main() method.