Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Normally, I'm not a big fan of centralized/global exception handling. My personal preference would be to either handle the exception everywhere or write your own proxy wrapper object that will handle/translate the expected fault exceptions.</p> <p>That said, there is an approach you can consider (though it requires modifying all your commands).</p> <p>First, factor the actual logic into an <code>async Task</code> method, as such:</p> <pre><code>public async Task MyCommandAsync() { try { using (var proxy = new MyProxy()) { var something = await proxy.GetSomethingAsync(); } } catch (FaultException&lt;MyFaultDetail&gt; ex) { // Do something here } } public async override void MyCommandImplementation() { MyCommandAsync(); } </code></pre> <p>Normally, I recommend implementing <code>async ICommand</code>s with an <code>async Task ExecuteAsync</code> method and matching <code>async void Execute</code> which will just do <code>await ExecuteAsync();</code>. The example I have above is almost the same except the <code>async void</code> method is <em>not</em> <code>await</code>ing the <code>Task</code>. This is dangerous and I'll explain below.</p> <p>Keeping your logic in an <code>async Task</code> gives you one tremendous advantage: you can unit test much more easily. Also, <code>async Task</code> methods have different exception handling which you can (ab)use to solve your problem.</p> <p>An <code>async Task</code> method - if the returned <code>Task</code> is never <code>await</code>ed - will raise <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.unobservedtaskexception.aspx" rel="nofollow"><code>TaskScheduler.UnobservedTaskException</code></a>. Note that this will <em>not</em> crash your process (as of .NET 4.5); your handler must decide the best response. Since your <code>async void</code> method is <em>not</em> <code>await</code>ing the <code>Task</code> returned by your <code>async Task</code> method, any exceptions will end up in <code>UnobservedTaskException</code>.</p> <p>So that will work, but it has one serious side effect: <em>any</em> unobserved <code>Task</code> exception will end up in the same handler (not just ones from your <code>ICommand</code>s). The reason that unobserved task exceptions were changed in .NET 4.5 to be ignored by default is because <em>that situation is no longer unusual</em> in <code>async</code> code. For example, consider this code which will attempt to download from two different urls and take the first response:</p> <pre><code>async Task&lt;string&gt; GetMyStringAsync() { var task1 = httpClient.GetAsync(url1); var task2 = httpClient.GetAsync(url2); var completedTask = await Task.WhenAny(task1, task2); return await completedTask; } </code></pre> <p>In this case, if the slower url results in an error, then that exception will be sent to <code>UnobservedTaskException</code>.</p>
    singulars
    1. This table or related slice is empty.
    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. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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