Note that there are some explanatory texts on larger screens.

plurals
  1. POGlobally catch exceptions thrown from WCF async calls in a background thread
    primarykey
    data
    text
    <p>I have a WPF application that communicates with a WCF service. I'm currently calling my WCF service from my ViewModels (I'm using the MVVM pattern) using the following <code>async</code> based pattern:</p> <pre><code>public async override void MyCommandImplementation() { using (var proxy = new MyProxy()) { var something = await proxy.GetSomethingAsync(); this.MyProperty = something; } } </code></pre> <p>As I'm following the MVVM pattern, I have <code>ICommand</code> public properties that are exposed by my ViewModels, so associated command implementation won't return <code>Task&lt;T&gt;</code> objects as they are like event handlers. So the exception handling is actually pretty simple, i.e. I am able to catch any exception thrown from my WCF service using the following pattern:</p> <pre><code>public async override void MyCommandImplementation() { try { using (var proxy = new MyProxy()) { var something = await proxy.GetSomethingAsync(); } } catch (FaultException&lt;MyFaultDetail&gt; ex) { // Do something here } } </code></pre> <p>So far so good, everything work as expected if the server throws an exception that is automatically converted to a SOAP Fault thanks to a custom WCF behavior.</p> <p>As I have some common exceptions that can be thrown everywhere in my service (for instance each WCF operation can throw a <code>AuthenticationException</code> that'll by converted on client side to a <code>FaultException&lt;AuthenticationFaultDetail&gt;</code> exception), I've decided to handle some exceptions in a common place in my application, i.e. by handling the <code>Application.DispatcherUnhandledException</code> event. This works just fine, I can catch all my <code>FaultException&lt;AuthenticationFaultDetail&gt;</code> exceptions everywhere, display an error message to the user, and prevent the application from exiting:</p> <pre><code>private static void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { // Exception handler that handles some common exceptions // such as FaultException&lt;AuthenticationFaultDetail&gt; if (GlobalExceptionHandler.HandleException(e.Exception)) { // Expected exception, so we're fine e.Handled = true; } else { // We're not fine. We couldn't handle the exception // so we'll exit the application // Log...etc. } } </code></pre> <p>Everything works pretty well because <code>FaultException</code> are thrown in the UI thread thanks to the <code>async</code> pattern and the synchronization context switch before/after the <code>await</code> keyword.</p> <p>My problem is, other exception can be thrown in another thread than my UI thread, for example in case of <code>EndPointNotFoundException</code> thrown at the <code>await proxy.GetSomethingAsync();</code> line (case of WCF service shutdown on server side).</p> <p>Those exceptions won't be handled in the <code>Application.DispatcherUnhandledException</code> event handler because they are not thrown in the UI thread. I can handle them in the <code>AppDomain.UnhandledException</code> event, but I'm not able to do anything else than do some logging and exit the application (there is basically no "e.Handled"-like property).</p> <p>So my question is: how could I handle exceptions thrown in background threads in case of an async WCF call in one place of my application?</p> <p>The best I can think of right now is something like the following:</p> <pre><code>public class ExceptionHandler : IDisposable { public void HandleException(Exception ex) { // Do something clever here } public void Dispose() { // Do nothing here, I just want the 'using' syntactic sugar } } ... public async override void MyCommandImplementation() { using (var handler = new ExceptionHandler()) { try { using (var proxy = new MyProxy()) { var something = await proxy.GetSomethingAsync(); } } catch (FaultException&lt;MyFaultDetail&gt; ex) { // Do something here } catch (Exception ex) { // For other exceptions in any thread handler.HandleException(ex); } } } </code></pre> <p>But this would require me to refactor a lot of code (each time I asynchronously call a web service).</p> <p>Any idea that would allow me to <em>not</em> refactor a huge amount of code would be helpful.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload