-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
What should I do with the global exception? #5290
Comments
// Here we subscribe to ReactiveUI default exception handler to avoid app
// termination in case if we do something wrong in our view models. See:
// https://www.reactiveui.net/docs/handbook/default-exception-handler/
//
// In case if you are using another MV* framework, please refer to its
// documentation explaining global exception handling.
RxApp.DefaultExceptionHandler = Observer.Create<Exception>(Console.WriteLine); |
The same problem is not solved |
Anything new on this issue? |
@olgaMuravjova since DispatcherUnhandledException or any other global unhandled exception handling, which prevents app from crashing, (and most possibly being trapped in invalid state) is considered as a bad practice, we don't really plan to support it. If you want to handle global errors, you can catch them in Program.Main method, log and close the app peacefully (restart or open report-error app if needed). Any other expected errors should be handled explicitly in place where they are expected. Alternatively, as it was mentioned above, if you are using ReactiveUI with your app, this library actually provides DefaultExceptionHandler for exceptions inside of observables. Though in most cases it means that Observable pipeline now in error state and won't work anymore. |
We now have docs for this 🚀 : https://docs.avaloniaui.net/docs/getting-started/unhandledexceptions |
I tried starting the app with try
{
BuildAvaloniaApp<TApp>()
.StartWithClassicDesktopLifetime(args);
}
catch (Exception ex)
{
MessageBox.Avalonia.MessageBoxManager.GetMessageBoxStandardWindow("Application Error", ex.ToString(), ButtonEnum.Ok,
Icon.Error);
} Also calling GlobalErrorHandler.Set on startup public class GlobalErrorHandler : IObserver<Exception>
{
private readonly IDialogService _dialogService;
public static void Set(Window owner)
{
var errHandler = Locator.Current.GetService<GlobalErrorHandler>()!;
errHandler.Owner = owner;
RxApp.DefaultExceptionHandler = errHandler;
}
public GlobalErrorHandler(IDialogService dialogService)
{
_dialogService = dialogService;
}
public Window? Owner { get; set; }
public async void OnNext(Exception error)
{
if (Debugger.IsAttached) Debugger.Break();
var _ = await _dialogService.ShowMessageBoxAsync(Owner, error.ToString(), "Application Error", MessageBoxButton.Ok, MessageBoxImage.Error);
}
public void OnError(Exception error)
{
if (Debugger.IsAttached) Debugger.Break();
}
public void OnCompleted()
{
if (Debugger.IsAttached) Debugger.Break();
}
} Clicking a button that calls this command. public ICommand AddFiles => _addFiles ??= ReactiveCommand.Create(AddFilesImpl);
private ICommand? _addFiles;
private async Task AddFilesImpl()
{
throw new InvalidOperationException();
} Neither of the 2 methods catches the error. What am I missing? Using Avalonia v0.10.15 |
I think you cannot show an Avalonia Window after the App is corrupt. If you know a method can throw, catch the exception locally. In the global try catch you can write to a log file. If you need to open a new window, I think you should start a separate app. Hope this helps Happy coding |
Except that here the global try catch isn't catching anything. |
Oh I don't know about ReactiveUI async Commands. I use MVVM CommunityToolkit with source generators. In there it works for me. |
ReactiveUI can be tricky sometimes. You might find more answers in their repository as well. |
@mysteryx93 well, I haven't noticed one sure issue in your code. public ICommand AddFiles => _addFiles ??= ReactiveCommand.CreateFromTask(AddFilesImpl); // Instead of .Create()
private ICommand? _addFiles;
private async Task AddFilesImpl()
{
throw new InvalidOperationException();
} |
The point is not just to prevent crashing ( which can be done on another level, like at Program.cs), but rather to write appropriate handling.
This is wrong statement, we can not know the probability of wrong state for every particular exception in general
Exceptions, how they are built in .NET are supposed to be handled exactly this way, they can bubble up thru several levels up the stack to the appropriate handler. Nobody said before it's bad practice. Here, i gave example of the usage: #8418 (comment)
Exceptions in .NET are part of execution flow control, not necessary the way to close the application.
This method would introduce code duplication which never does make sense.
As mentioned, this can not be used because Observable pipeline does not properly handle exceptions |
I'm still unable to catch the exception. I call Also tried with this. AppDomain.CurrentDomain.UnhandledException += (x, e) =>
{
var a = "";
}; Set breakpoints, run my infamous command, and.... nothing. public ICommand AddFolder => _addFolder ??= ReactiveCommand.CreateFromTask(AddFolderImpl);
private ICommand? _addFolder;
private async Task AddFolderImpl()
{
throw new InvalidOperationException("You failed.");
} Which is a bummer, because it really fails on MacOS and I got no way to diagnose. The only way I'm succeeding at handling the exception is by creating an extension method and call
|
Reproduced the issue in a blank project template; since this ticket is closed, created a new issue about it. |
In Android project, I can not find a Main function. |
I modified a set of my own code to handle global exceptions, and there are 2 ways to tweak it. way1
way2
But I don't know which one makes the most sense this is the core code I Modified.
|
Exception should end up on AppDomain.UnhandledException, right? So a tool like Sentry should help with useful context to what went wrong (stack trace, line numbers, breakdown by OS, logs/breadcrumbs etc). I got to this issue because we (Sentry) want to know if there are additional hooks we need to catch any type of error coming from Avalonia, or if we need a dedicated integration |
@bruno-garcia |
Whether there is a mechanism like wfp's DispatcherUnhandledException, my logic is that Project A refers to Project B, project B throws an exception, but not fatally just a hint. I want the program to continue running instead of exiting the program.
Any suggestions or best practices?
I still don't find useful information through search engines, which is the only relevant introduction I've found so far, but I don't quite understand how to use this
https://gitter.im/AvaloniaUI/Avalonia?at=5d833ca2a7a5cc473319c6ed
https://www.reactiveui.net/docs/handbook/default-exception-handler/
The text was updated successfully, but these errors were encountered: