OpenRIAServices / OpenRiaServices

The Open RIA Services project continues what was previously known as WCF RIA Services.
https://openriaservices.gitbook.io/openriaservices/
Apache License 2.0
54 stars 47 forks source link

How to handle exception in callbacks for the synchronous methods (Load, Submit, Invoke) of a DomainContext? #424

Closed aud0201 closed 11 months ago

aud0201 commented 1 year ago

Hello,

I am converting a legacy Silverlight project to a WPF project. I am glad that Open Ria Service makes this possible.

I have one question. I mainly use the Completed event of OperationBase when using callback, but when an exception occurs within the event, it is not caught in the MainThread

This seems to occur in the same way in Sync methods such as Load, Submit, and Invoke, and if an exception occurs, it must be handled so that MainThead can know it.

domainContext.Load(domainContext.GetSomeQuery()).Completed += (s1, e1) => 
{
    throw new Exception("something");   // when ouccur some exception,  App.DispatcherUnhandledException cannot handle

};

Is there a good way to solve this?

Thanks

SandstromErik commented 1 year ago

Hi @aud0201!

Since all operations are asynchronous the exceptions are thrown asynchronously aswell. In order to handle exceptions you need to check for errors in the callback method. This documentation contains more details: https://openriaservices.gitbook.io/openriaservices/ee707349/ee807307

aud0201 commented 1 year ago

First of all, thank you for your answer. I guess my question was not clear enough.

I think the callback method should check for errors from the server, as described in the link you provided.

However, it is strange that if an error occurs in the business process within the client after the callback, it is not handled by App.DispatcherUnhandledException.


    private void cmdLoadData_Click(object sender, RoutedEventArgs e)
    {
      MainDoS domainContext = new MainDoS();

      domainContext.Load(domainContext.GetMembersQuery(), OnCompleted, null);
    }

    private void OnCompleted(LoadOperation lo)
    {
      if (lo.HasError)
      {
        MessageBox.Show(string.Format("Retrieving data failed: {0}", lo.Error.Message));
        lo.MarkErrorAsHandled();
      }
      else
      {
        BizProcess(); 
      }
    }

    private void BizProcess()
    {
      // Some Business Logic
      // ...
      // ... 
      // ...
      // An error occurred while executing the business logic after the data was loaded.
      // but this exception is not handled App.DispatcherUnhandledException.
      throw new Exception("Some Exception");  
    }
Daniel-Svensson commented 1 year ago

@aud0201 It seems like exceptions from callbacks needs to be handled using TaskScheduler.UnobservedTaskException handler instead (at least sometimes) .

I believe this happened in version 5.0 and was an unintended change so it is not documented. A noticable difference is that TaskScheduler.UnobservedTaskException will not fire immediately but with some delay.

It should be fixable if very important, but I am a bit unsure about effort and when.

It might be simpler to just use an older version or maybe rewrite the code somewhat (maybe use the async methods for easier error handling) or an own extension method which captures the current SyncronizationContext and use that to invoke the callback.

aud0201 commented 1 year ago

Hi, Daniel

thanks for the answer

But TaskScheduler.UnobservedTaskException is currently not working for me.

As you said, using an async method seems to be the best way.

If you have time, could you please let me know if any ideas I have come up with can help me solve this problem? #427