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

[Question]: How to use ExecuteAsync In VB.Net? #2045

Closed
ricfwolff opened this issue Apr 9, 2024 · 8 comments · Fixed by #2046
Closed

[Question]: How to use ExecuteAsync In VB.Net? #2045

ricfwolff opened this issue Apr 9, 2024 · 8 comments · Fixed by #2046
Labels

Comments

@ricfwolff
Copy link

What are you wanting to achieve?

Sorry to bring VB.Net... But some of us still need to work with it. :)

I'm trying to add Polly v8 to a vb.net project, but I'm facing a compiler error when I try to use the ExecuteAsync method:

image

I noticed the ExecuteAsync method returns "ValueTask" instead of "Task". And it looks like that might be the problem...

What code or approach do you have so far?

I also noticed that I can exchange ExecuteAsync for Execute and the compiler will stop complaining about it, but there's another post here on your GitHub explaining that we shouldn't do it, and anyway I tried and my RetryStrategy does not work. :(

Could someone please point me to what I'm doing wrong?

Thank you!

Additional context

No response

@martincostello
Copy link
Member

Have you tried using AsTask() to convert the ValueTask{<T>} to a Task{<T>}? I haven't done any VB since about 2002, but that should make the compiler happy if it requires an async function to return Task{<T>}?

@ricfwolff
Copy link
Author

It does not work :(
Because it's expecting the callback to be of ValueTask:

image

But I cannot modify the callback because it'll throw compiler errors as well.
I'm not sure what's wrong here...

Maybe a question for StackOverflow instead.

@martincostello
Copy link
Member

Not as readable, but does something like this work (pseudocode as I no VB gud):

var returnData = await RetryStrategy.ExecuteAsync(SomeFunction).AsTask()

ValueTask(Of Result) SomeFunction(CancellationToken token)
{
    var thing = Async Function(token) { /* What you do in your user code */ }
    return new ValueTask(Of Result)(thing)
}

Essentially wrapping your async function that uses Task inside a method that isn't async and just returns a ValueTask that will await your database query.

@ricfwolff
Copy link
Author

Good idea, I'll try that out and let you know. Thanks!

@martincostello
Copy link
Member

I just tried this out locally and it seems to work:

Imports System.Threading
Imports Polly

Module Program
    Sub Main()
        Demo().Wait()
    End Sub

    Async Function Demo() As Task
        ' The ResiliencePipelineBuilder creates a ResiliencePipeline
        ' that can be executed synchronously or asynchronously
        ' and for both void and result-returning user-callbacks.
        Dim pipeline = New ResiliencePipelineBuilder().AddTimeout(TimeSpan.FromSeconds(5)).Build()

        ' Synchronously
        pipeline.Execute(Sub()
                             ' Do something synchronously
                         End Sub)

        Await pipeline.ExecuteAsync(Function(token)
                                        Return New ValueTask(MyAsyncCallback(token))
                                    End Function, CancellationToken.None).AsTask()
    End Function

    Function ExecuteAsync(pipeline As ResiliencePipeline, callback As Func(Of CancellationToken, ValueTask), cancellationToken As CancellationToken) As Task
        Return pipeline.ExecuteAsync(callback, cancellationToken).AsTask()
    End Function

    Async Function MyAsyncCallback(token As CancellationToken) As Task
        Console.WriteLine("Waiting for 1 second")
        Await Task.Delay(1000, token)
    End Function
End Module

@ricfwolff
Copy link
Author

I was able to make it work using the idea you gave me (code below for future vb.net sad fellows).
But, in my situation, I'll have to write too much code for what I'm trying to attempt (which is just retry up to 5 times when connection in the pool is lost). So I'll make my own simpler method to handle it, only because I was using only 1% of Polly's feature. It's not Polly's fault, it's my bad legacy code. :)

Thank you!

    Protected Async Function GetDataFromDBToDataTableAsync(sql As String, Optional param As OracleParameter() = Nothing) As Task(Of DataTable)
        Dim callback As Func(Of CancellationToken, ValueTask(Of DataTable)) =
            Function(token)
                Return New ValueTask(Of DataTable)(ThingFunction(sql, param))
            End Function

        Dim returnData = Await RetryStrategy.ExecuteAsync(callback)

        Return returnData
    End Function

    Async Function ThingFunction(sql As String, Optional param As OracleParameter() = Nothing) As Task(Of DataTable)
        Dim result As New DataTable

        Using conn = New OracleConnection(L3ConnectionString)
            Using sqlCommand = New OracleCommand(sql, conn)
                sqlCommand.CommandTimeout = 600
                sqlCommand.BindByName = True

                If (param IsNot Nothing AndAlso param.Length > 0) Then
                    sqlCommand.Parameters.AddRange(param)
                End If

                Using dataAdapter As New OracleDataAdapter(sqlCommand)
                    Await Task.Run(Sub() dataAdapter.Fill(result))
                End Using
            End Using

            conn.Close()
        End Using
        Return result
    End Function

@ricfwolff
Copy link
Author

Thank you!

Yes, it works. But VB asks for too much code.

Thank you anyway! I hope to migrate this code to C# soon. :)

martincostello added a commit to martincostello/Polly that referenced this issue Apr 9, 2024
@martincostello
Copy link
Member

Thanks for asking the question - I wasn't aware that ValueTask is difficult to use in VB.NET (and F#!) compared to C#.

I've created #2046 to extend our documentation for future consumers using those languages.

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

Successfully merging a pull request may close this issue.

2 participants