Visual Studio 2015. If I write code in C #, then everything works:

private async void Form1_Load(object sender, EventArgs e) { try { await Task.Delay(1000); this.Text = "Text from try"; throw new Exception(); } catch (Exception) { await Task.Delay(1000); this.Text = "Text from catch"; } finally { await Task.Delay(1000); this.Text = "Text from finally"; } } 

But if on VB.NET, then I get a compilation error:

Error BC36943 'Await' cannot be used inside a 'Catch' statement, a 'Finally' statement, or a 'SyncLock' statement.

 Public Class Form1 Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Try Await Task.Delay(1000) Me.Text = "Text from Try" Throw New Exception() Catch ex As Exception Await Task.Delay(1000) Me.Text = "Text from Catch" Finally Await Task.Delay(1000) Me.Text = "Text from Finally" End Try End Sub End Class 

Why is it not compiled? Am I doing something wrong?

  • await in catch appeared only in C # 6 - maybe in VB it wasn’t a ride yet ? - VladD
  • @VladD, they promised to add new features at the same time? Or is it not? :( - Qwertiy
  • Well, for example, filters in catch in VB were a long time ago, I got jealous, until they finally added to C #. We for this purpose somehow even specially wrote the module on VB. // They try at the same time, but apparently did not have time in the last release. - VladD
  • @VladD, there is a lot of 6th Sharp there for a long time. For example, using static and initialization properties (normal). What if I need await in catch or finally? - Qwertiy

1 answer 1

Unfortunately, the await in catch / finally feature in the current version of VB did not have time to break through , it is promised in the next version.

For the current version, you can use the dirty ugly manual path that I worked on in C # 5.

Code

 try { // ... } catch (SomeException ex) { await CatchTask(); if (cond) throw; } finally { await FinallyTask(); } 

corresponded as

 Imports System.Runtime.ExceptionServices 
 Dim exinfo As ExceptionDispatchInfo = Nothing Dim needCatch As Boolean = False Try ' ... Catch ex As Exception exinfo = ExceptionDispatchInfo.Capture(ex) needCatch = TypeOf ex Is SomeException End Try If needCatch Then Await CatchTask() If Not cond Then exinfo = Nothing End If Await FinallyTask() If exinfo IsNot Nothing Then exinfo.Throw() 

ExceptionDispatchInfo needed to keep the correct stack in the exception.

For the case when there is no throw , catch or finally , the code can be pretty much simplified.

  • Hmm .. Manual dispatch exceptions :) - Qwertiy
  • @Qwertiy: Yep, sunset manually. : - \ - VladD
  • Some kind of incorrect you finally - if the exception is not SomeException, then it will go to the forest ... - Qwertiy
  • @Qwertiy: Right! I'll fix it now. - VladD
  • @Qwertiy: That seems to be the final version, check the logic. - VladD