Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Champion "Await in Catch and Finally" #37

Open
gafter opened this issue Feb 26, 2017 · 17 comments
Open

Champion "Await in Catch and Finally" #37

gafter opened this issue Feb 26, 2017 · 17 comments

Comments

@gafter
Copy link
Member

gafter commented Feb 26, 2017

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

@gafter gafter added this to the VB15.x candidate milestone Feb 26, 2017
@vbcodec
Copy link

vbcodec commented Feb 27, 2017

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

@gafter
Copy link
Member Author

gafter commented Feb 28, 2017

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

@vbcodec
Copy link

vbcodec commented Feb 28, 2017

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

@gafter
Copy link
Member Author

gafter commented Feb 28, 2017

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

@AnthonyDGreen
Copy link
Contributor

@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
Copy link
Member

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

@AnthonyDGreen
Copy link
Contributor

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
Copy link
Member

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

@AnthonyDGreen
Copy link
Contributor

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
Copy link
Contributor

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
Copy link

tb-mtg commented Jan 18, 2018

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
Copy link

chucker commented Jan 22, 2021

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
Copy link

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
Copy link

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
Copy link

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

@nick4814
Copy link

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
Copy link

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/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests