dotnet / vblang

The home for design of the Visual Basic .NET programming language and runtime library.
290 stars 66 forks source link

Champion "Await in Catch and Finally" #37

Open gafter opened 7 years ago

gafter commented 7 years ago

VB doesn't allow this today and C# does. Seems like it could be a pain if APIs require this pattern a lot.

There are special design considerations required for VB as in VB it is permitted to Goto from the Catch block back into the Try block. This would complicate the state machine rewrite a bit:

dim retryCount = 0 try retry: catch ex as Exception When retryCount < 3 retryCount += 1 goto retry end try

vbcodec commented 7 years ago

Will it be ready for VS 2017 RTM ? On roslyn repo it was proposal for quite some time

gafter commented 7 years ago

We are "done" with the compiler for VS2017 RTM and the work for this has not started.

vbcodec commented 7 years ago

I am disappointed. This is most missing feature. Will it be avalable in some VS 2017 update ?

gafter commented 7 years ago

@vbcodec We do not make product announcements on github. Usually product announcements and plans would be found on the Visual Studio Blog.

AnthonyDGreen commented 7 years ago

@vbcodec we do have the ability to ship it in an update, though as Neal says, we can't commit to if it would ship in an update or which update it would ship in. We don't usually commit to features in updates this early given that our highest priorities for them are bug fixes, performance improvements, and reacting to other feedback from the RTW.

KlausLoeffelmann commented 7 years ago

So, what is the current status on this? Has this discussed lately in any LDMs?

AnthonyDGreen commented 7 years ago

There is nothing to discuss. There feature is self explanatory. There may be questions that come up during implementation but there's nothing to design at this point.

KlausLoeffelmann commented 7 years ago

With "discuss"I mean, has it somehow prioritized that an actual implementation will begin?

AnthonyDGreen commented 7 years ago

We have not announced a schedule for any features post 15.3. That process is on-going and the recent activity on this repo are specifically motivated to get more transparency into the backlog. When that process produces a schedule we're confident in enough to share it'll be published here and on the Roslyn repo.

AnthonyDGreen commented 7 years ago

The VB LDM looked at this proposal on August 9th and approved it in-principle. We also decided not to restrict VBs existing permissiveness with Goto in the Catch block in the presence of an Await; we should just do the work to make it work. We haven't scheduled it since the priority of the feature is unclear. We believe that IAsyncDisposable and Async Using which we're looking at for VB 16/C# 8 would naturally raise the priority of this. Additional real-word customer scenarios would be needed to raise its priority before that.

tb-mtg commented 6 years ago

Here's a scenario, snippets taken from taken from the ASP.NET docs sample project for
ContosoUniversity RazorPages that has been converted to VB

 If Await TryUpdateModelAsync(Of Department)(departmentToUpdate, "Department", Function(s) s.Name, Function(s) s.StartDate, Function(s) s.Budget, Function(s) s.InstructorID) Then
        Try
          Await _context.SaveChangesAsync()
          Return RedirectToPage("./Index")
        Catch ex As DbUpdateConcurrencyException
          Dim exceptionEntry = ex.Entries.Single()
          Dim clientValues = CType(exceptionEntry.Entity, Department)
          Dim databaseEntry = exceptionEntry.GetDatabaseValues()
          If databaseEntry Is Nothing Then
            ModelState.AddModelError(String.Empty, "Unable to save. " & "The department was deleted by another user.")
            Return Page()
          End If
          Dim dbValues = CType(databaseEntry.ToObject(), Department)
          Await setDbErrorMessage(dbValues, clientValues, _context)
          ' Save the current RowVersion so next postback
          ' matches unless an new concurrency issue happens.
          Department.RowVersion = CType(dbValues.RowVersion, Byte())
          ' Must clear the model error for the next postback.
          ModelState.Remove("Department.RowVersion")
        End Try
      End If
    Private Async Function setDbErrorMessage(dbValues As Department, clientValues As Department, context As SchoolContext) As Task
      If dbValues.Name <> clientValues.Name Then
        ModelState.AddModelError("Department.Name", $"Current value: {dbValues.Name}")
      End If
      If dbValues.Budget <> clientValues.Budget Then
        ModelState.AddModelError("Department.Budget", $"Current value: {dbValues.Budget:c}")
      End If
      If dbValues.StartDate <> clientValues.StartDate Then
        ModelState.AddModelError("Department.StartDate", $"Current value: {dbValues.StartDate:d}")
      End If
      If dbValues.InstructorID <> clientValues.InstructorID Then
        Dim dbInstructor As Instructor = Await _context.Instructors.FindAsync(dbValues.InstructorID)
        ModelState.AddModelError("Department.InstructorID", $"Current value: {dbInstructor?.FullName}")
      End If
      ModelState.AddModelError(String.Empty, "The record you attempted to edit " & "was modified by another user after you. The " & "edit operation was canceled and the current values in the database " & "have been displayed. If you still want to edit this record, click " & "the Save button again.")
    End Function
chucker commented 3 years ago

Seems like it could be a pain if APIs require this pattern a lot.

Now that IAsyncDisposable has shipped, this seems to have become a bigger pain.

craigajohnson commented 3 years ago

Yes please and this is also just so frustrating. IAsyncDisposable also presupposes VB support for an Async function that returns ValueTask which it absolutely should have. It is sick and wrong to have to carve out exceptions, write C# helper functions, etc., just to get a seat at the table with the big kids.

DualBrain commented 3 years ago

I'm not a regular user of C#... so my take on this is purely as a consumer of VB. In other words, I don't give a rats rear-end regarding what C# is or isn't capable of doing or how it does it. With that out of the way...

It does seem rather annoying that it isn't possible to utilize Await in a Catch block.

One recent example where I've encountered this (and it's not a unique occurrence)... and, yes, was able to "work around" was when I wanted in an Async function that has a multiple phases to work through. It is entirely possible to have an exception occur and, in the event one does occur, I'd like to update my visual layer (WinForms) so that there is a visible indication of this happening. To do this I have a Label on the Form and would like to update it with a comment stating that a particular step has failed. Simple enough to update the .Text value. However, I'd also like to add a bit of a delay... my choices are...

In the Catch block:

MessageLabel.Text = "It failed because...": Threading.Thread.Sleep(2000)

--- OR ---

Before the Try block:

Dim errorMessage As String = Nothing

In the Catch block:

errorMessage =  "It failed because..."

After the Try block:

If errorMessage IsNot Nothing Then
   MessageLabel.Text = errorMessage: Await Task.Delay(2000)
   errorMessage = Nothing ' To clear it out for the (maybe) next time further down in the code.
End If

Both of these will work with what we currently have... however, in order to not lock up the UI, I have to do something in three different places in the code and this is something that could easily lead to human error over time as the project evolves.

If I could simply switch out the thread-locking version with:

MessageLabel.Text = "It failed because...": Await Task.Delay(2000)

The code is clean and there isn't the penalty of locking the UI.

I'm sure there are other scenarios where this is the case... just bringing this one up as I literally run into it constantly.

Videstra commented 3 years ago

it's 2021, has this functionality (await inside catch for VB) been eliminated as a possibility?

nick4814 commented 4 months ago

it's 2021, has this functionality (await inside catch for VB) been eliminated as a possibility?

I don't think MS cares at all about VB sadly. Would be nice to get Enum extension functionality like C# too. MS has a nice track record of abandoning things, so I doubt they will do anything and let it die.

paul1956 commented 4 months ago

VB is only being enhanced when a .Net library requires it to avoid breaking compatibility. That is why VB got all the Record stuff. VB needs to be a consumer of library's but new library's don't need to be written in VB. Maximum performance is not a priority for Vb, compatibility is. If you want new features look at the work by Anthony D. Green http://anthonydgreen.net/