I am trying to use a GraphicsCapturePicker from the code-behind in a MAUI app and am hitting a COM exception implying I am calling this from the wrong thread. Typically code in WPF/XAML code-behind files are dispatched from the main thread so I am a bit confused about what's going wrong here:
// A regular button event handler in MainPage.xaml.cs
private void OnScreenCaptureClicked(object sender, EventArgs e)
{
var picker = new GraphicsCapturePicker();
GraphicsCaptureItem item = picker.PickSingleItemAsync().GetResults();
}
Throws exception:
"The application called an interface that was marshalled for a different thread"
Exception thrown: 'System.Runtime.InteropServices.COMException' in System.Private.CoreLib.dll
Note: In the above example I am calling the method syncronously as a test to make it easier to catch the exception, the same thing happens when it's wrapped in a task.
This exact code works fine in a regular non-MAUI UWP/C# project.
Related
My application is giving an error 'specified method is not supported' on a client pc. I do not know where the problem is coming from. He does not have Visual Studio installed so its impossible to debug.
Is there any way to get a call stack in WPF if I write some debug code in the application and give him the new exe?
You can subscribe to DispatcherUnhandledException to capture the unhandled exception at application level and to log stack trace of exception.
Example of DispatcherUnhandledException in App.xaml.cs
public App() {
this.DispatcherUnhandledException += OnDispatcherUnhandledException;
}
void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) {
string errorMessage = string.Format("An unhandled exception occurred: {0}", e.Exception.Message);
MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
e.Handled = true;
}
In a big picture you can capture a exception at :
You can trap unhandled exceptions at different levels:
AppDomain.UnhandledException From all threads in the AppDomain.
Dispatcher.UnhandledException From a single specific UI dispatcher
thread.
Application.DispatcherUnhandledException From the main UI
dispatcher thread in your WPF application.
TaskScheduler.UnobservedTaskException from within each AppDomain
that uses a task scheduler for asynchronous operations. You should
consider what level you need to trap unhandled exceptions at.
Deciding between #2 and #3 depends upon whether you're using more than one WPF thread.
I need to get the CurrentState from a MediaElement several times. I've created a simple function that looks like this:
private string getCurrentState(MediaElement m)
{
return m.CurrentState.ToString();
}
But everytime this function is called I get this:
An exception of type 'System.Exception' occurred in MyProject but was not handled in user code.
Additional information: The application called an interface that was marshalled for a different thread.
(Exception gfrom HRESULT: 0x8001010E (RCP_E_WRONG_THREAD))
I've been investigating about this issue and, as I've understood, it usually comes when trying to retrieve the CurrentState before the MediaOpenedevent's been fired. Actually, this not suits my case since this function is called after that. However I call the CurrentStateproperty I get the same exception and the weirdest thing of this all is that sometimes works, and sometimes not, so I definetely have got no idea of what is wrong in the code :S
Does anyone have any idea about how to fix it?
You are trying to get state from Non-ui thread. You should redesign you code to not interact with MediaElement from background thread (Task).
Or you can wrap getCurrentState method invocation into Despatcher
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
<lambda for your code which should run on the UI thread>);
WPF provides a very convenient way to handle unexpected exceptions: I can just attach a handler to the Application.DispatcherUnhandledException event and all unhandled exceptions go this way:
Application.Current.DispatcherUnhandledException += (sender, e) => {
// Show message, log exception, etc.
};
This works great for WPF application projects. Now, I have a library with WPF windows, which is called from a non-WPF application (it's a legacy VBA app, and the WPF library is made accessible via COM interop).
So, the thing is: I can create, open and show WPF windows (this works fine), but I don't have an Application instance. Application.Current is null. I use the WPF classes, but I operate them outside the WPF application framework.
Currently, the only drawback of this solution is that exceptions in WPF window event handler code are silently swallowed:
void Button_click(sender as object, e as RoutedEventArgs) {
...
// some exception occurs here, but nobody hears her scream
...
}
I don't like that. I'd like to log them and show error messages.
My question: Is there a way to globally catch unhandled exceptions in this scenario or do I have to add a gerneric try-catch-log block to every WPF window event handler code I write?
What I have tried:
Attaching to AppDomain.CurrentDomain.UnhandledException. Doesn't work. Exceptions don't get there.
Reading the relevant parts of MSDN regarding WPF and Win32 interop (Ref 1, Ref 2, Ref 3). Exceptions are not mentioned there.
Attach to the Dispatcher instead:
Dispatcher.CurrentDispatcher.DispatcherUnhandledException += (sender, e) => {
// Show message, log exception, etc.
};
If no dispatcher exists yet, accessing CurrentDispatcher automatically creates a singleton Dispatcher which will also be used by the WPF windows.
I have a program that, among other things, needs to be able to refresh the contents of a directory when the user tells it to. The actual task doesn't really matter, but this is the simplest way of causing this problem to occur that I know of.
If I tell it to open a directory that doesn't exist, I get the "unhandled exception" dialog in VS with a stack trace of, from outer to inner:
[External code]
Textbox PreviewKeyUp event
[External code]
ClassA's path property being set
ClassA's internal path update function being called
A call to the INotifyPropertyChanged event
[External code]
A call to the getter for ClassB's list of children
A call to ClassB's internal directory list function
And then it fails inside this internal function. I have the following in my App.xaml.cs:
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Current.Dispatcher.UnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(Dispatcher_UnhandledException);
}
But neither of their exception handlers are being called. If I run this program from outside VS, I don't get notified of an exception at all, it just breaks because of the invalid input. And yes, the Application_Startup event is being called. How can I properly "trap" this exception so I can provide a friendly error message and kill the program?
Oh, and if I put a try/catch anywhere up the call stack past an External Code call, it doesn't catch it, either.
[edit]
After some searching, I'm pretty sure this is a side effect of WPF's binding system. Because the DirectoryInfo is being created successfully (even on a directory that doesn't exist), the error doesn't occur until a binding goes to retrieve the value - and WPF eats binding exceptions.
I'm leaving this open in case anyone has any further ideas, but I think I the best I can do is abandon lazy-loading if I think it can lead to exceptions, at least until the application is more proven.
Try attaching to the apps DispatcherUnhandledException.
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Current.Dispatcher.UnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(Dispatcher_UnhandledException);
this.DispatcherUnhandledException += ...
}
I have a SCSF application i am trying to handle most of the exceptions using
Application.ThreadException += new ThreadExceptionEventHandler(new ThreadExceptionHandler().ApplicationThreadException);
The event handler :-
public class ThreadExceptionHandler
{
public void ApplicationThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "An exception occurred:", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Works fine . I can catch all the application exceptions in this block.
But the problem is after handling the exception the code again goes and executes the same exception generating code again. This happens till the time I get a windows message windows to send the error info to microsoft.
Could any one please help in telling me where I might be going wrong.
Thanks in Advance
Vikram
Note :- Currently i am throwing
New Exception("Test Exception"); from a button event. I am doing this to provide event handling in my application.
You have to set
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
See this MSDN page for example code
But note that this kind of catch-all exception handling is not a good replacement for exception handling inside your logic. It is a good backup, but the best thing to do in a global handler is to log the information and exit. Your app could be in an unsafe/undefined state.
After some banging my head against the code I found that the problem was due to the fact that my SCSF solution had a winforms Shell and on that shell there were WPF usercontrols.
When the exception where generated on these WPF usercontrol (mostly the case) they are not caught by
Application.ThreadException coz Application class for WPF is different than that for Winforms.
In WPF application one need to handle Application.DispacherUnhandledException event.
Just my little finding ...
you would be surprised by just handling the Application.DispatcherUnhandledException. I have worked with SCSF which had WPF user controls. Read through this post . http://social.msdn.microsoft.com/forums/en-US/wpf/thread/c57cac13-f960-49a1-94b5-a3fd316ac4bc/ i would recommend handling AppDomain.UnhandledException too.