-
Notifications
You must be signed in to change notification settings - Fork 777
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
Async Methods swallow exceptions #961
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,20 +103,33 @@ | |
|
||
if (!IsInitialized) | ||
{ | ||
try | ||
{ | ||
Log.Info("Initializing {0}.", this); | ||
#pragma warning disable CS0618 // Type or member is obsolete | ||
await OnInitializeAsync(cancellationToken); | ||
await OnInitializeAsync(cancellationToken); | ||
|
||
#pragma warning restore CS0618 // Type or member is obsolete | ||
IsInitialized = initialized = true; | ||
await OnInitializedAsync(cancellationToken); | ||
IsInitialized = initialized = true; | ||
await OnInitializedAsync(cancellationToken); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not something that was done here in this PR, but why was the name changed from OnInitializeAsync to OnInitializedAsync? This method is called when initializing so the initializing happens in the OnInitializeAsync thus the name OnInitializeAsync makes more sense then OnInitializedAsync since OnInitializedAsync implies that the initialization is already completed. |
||
} | ||
catch (Exception ex) | ||
{ | ||
Log.Error(ex); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, either all the methods should log the exception or there should be a OnException method that the user can hook into. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
} | ||
|
||
} | ||
|
||
Log.Info("Activating {0}.", this); | ||
try | ||
{ | ||
Log.Info("Activating {0}.", this); | ||
#pragma warning disable CS0618 // Type or member is obsolete | ||
await OnActivateAsync(cancellationToken); | ||
await OnActivateAsync(cancellationToken); | ||
|
||
#pragma warning restore CS0618 // Type or member is obsolete | ||
IsActive = true; | ||
await OnActivatedAsync(cancellationToken); | ||
|
||
IsActive = true; | ||
await OnActivatedAsync(cancellationToken); | ||
} | ||
catch (Exception ex) | ||
{ | ||
OnActivatedAsyncException(ex); | ||
} | ||
|
||
await (Activated?.InvokeAllAsync(this, new ActivationEventArgs | ||
{ | ||
WasInitialized = initialized | ||
|
@@ -134,7 +147,15 @@ | |
}); | ||
|
||
Log.Info("Deactivating {0}.", this); | ||
await OnDeactivateAsync(close, cancellationToken); | ||
try | ||
{ | ||
await OnDeactivateAsync(close, cancellationToken); | ||
} | ||
catch (Exception ex) | ||
{ | ||
OnDeactivateAsyncException(ex); | ||
} | ||
|
||
|
||
IsActive = false; | ||
|
||
await (Deactivated?.InvokeAllAsync(this, new DeactivationEventArgs | ||
|
@@ -206,6 +227,15 @@ | |
} | ||
|
||
|
||
/// <summary> | ||
/// Called when exception called in OnActivatedAsync. | ||
/// </summary> | ||
protected virtual void OnActivatedAsyncException(Exception thrownException) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This gets called when PS: Same for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the rename from OnActivateAsync to OnActivatedAsync should be reverted, since that function is called when the framework wants to activate the screen and not when it is already activated. |
||
{ | ||
Log.Info("Activated Async Exception"); | ||
Log.Error(thrownException); | ||
} | ||
|
||
/// <summary> | ||
/// Called when view has been activated. | ||
/// </summary> | ||
|
@@ -226,5 +256,23 @@ | |
Log.Info("Task deactivate"); | ||
return Task.FromResult(true); | ||
} | ||
|
||
/// <summary> | ||
/// Called when exception called in OnDectivateAsync. | ||
/// </summary> | ||
protected virtual void OnDeactivateAsyncException(Exception thrownException) | ||
{ | ||
Log.Info("Deactivate Async Exception"); | ||
Log.Error(thrownException); | ||
} | ||
|
||
/// <summary> | ||
/// Called when exception called in OnInitializedAsync. | ||
/// </summary> | ||
protected virtual void OnInitializedAsyncException(Exception thrownException) | ||
{ | ||
Log.Info("Initialized Async Exception"); | ||
Log.Error(thrownException); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ public class CaliburnApplication : Application | |
public CaliburnApplication(IntPtr javaReference, JniHandleOwnership transfer) | ||
: base(javaReference, transfer) | ||
{ | ||
|
||
} | ||
|
||
/// <summary> | ||
|
@@ -41,7 +41,7 @@ protected virtual void StartDesignTime() | |
|
||
/// <summary> | ||
/// Called by the bootstrapper's constructor at runtime to start the framework. | ||
/// </summary>B | ||
/// </summary> | ||
protected virtual void StartRuntime() | ||
{ | ||
AssemblySourceCache.Install(); | ||
|
@@ -131,5 +131,14 @@ protected virtual IEnumerable<object> GetAllInstances(Type service) | |
protected virtual void BuildUp(object instance) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Handles exceptions that occur during coroutine execution. | ||
/// </summary> | ||
/// <param name="sender">The sender of the event.</param> | ||
/// <param name="e">The event arguments containing exception details.</param> | ||
protected virtual void CoroutineException(object sender, ResultCompletionEventArgs e) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this ever be called? Isn't it missing the following in Coroutine.Completed += (s, e) =>
{
if (e.Error != null)
{
CoroutineException(s, e);
}
}; If yes then please also check: |
||
{ | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,6 @@ | |
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading.Tasks; | ||
using Microsoft.Maui.Controls; | ||
|
||
|
@@ -19,8 +18,10 @@ public abstract class MauiApplication : Application | |
/// <summary> | ||
/// Start the framework. | ||
/// </summary> | ||
protected void Initialize() { | ||
if (isInitialized) { | ||
protected void Initialize() | ||
{ | ||
if (isInitialized) | ||
{ | ||
return; | ||
} | ||
|
||
|
@@ -30,10 +31,11 @@ protected void Initialize() { | |
|
||
var baseExtractTypes = AssemblySourceCache.ExtractTypes; | ||
|
||
AssemblySourceCache.ExtractTypes = assembly => { | ||
AssemblySourceCache.ExtractTypes = assembly => | ||
{ | ||
var baseTypes = baseExtractTypes(assembly); | ||
var elementTypes = assembly.ExportedTypes | ||
.Where(t => typeof (Element).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())); | ||
.Where(t => typeof(Element).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())); | ||
|
||
return baseTypes.Union(elementTypes); | ||
}; | ||
|
@@ -44,6 +46,13 @@ protected void Initialize() { | |
IoC.BuildUp = BuildUp; | ||
|
||
AssemblySource.Instance.Refresh(); | ||
Coroutine.Completed += (s, e) => | ||
{ | ||
if (e.Error != null) | ||
{ | ||
CoroutineException(s, e); | ||
} | ||
}; | ||
} | ||
|
||
/// <summary> | ||
|
@@ -174,5 +183,12 @@ protected virtual IEnumerable<object> GetAllInstances(Type service) | |
protected virtual void BuildUp(object instance) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Called by the bootstrapper's constructor at design time to start the framework. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
/// </summary> | ||
protected virtual void CoroutineException(object sender, ResultCompletionEventArgs e) | ||
{ | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your comment you said that there was a private field added to this class but I only see the added constructor?