0

I need to pass a parameter to a Task (DotNet 4.0+) using the Task.Factory.StartNew syntax, but can't seem to figure out how to create an anonymous function in VB.Net (C# syntax is radically different and online converters do not work).

Here's the code (that looks like it would work, but most of the tasks have completed before the global variable can change in the iteration - so i need to pass that variable to the Task directly).

   Public CurrentTradeDataURL As String = String.Empty

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim tskGet_BTCE As Task(Of Trades.TradeData)() = New Task(Of Trades.TradeData)(17) {}
        For i As Integer = 0 To 17
            CurrentTradeDataURL = My.Settings.All_BTCE_URIs(i)
            tskGet_BTCE(i) = Task.Factory.StartNew(Of Trades.TradeData)(AddressOf GetTradeData) 
        Next

        Task.WaitAll(tskGet_BTCE)

        For x As Integer = 0 To 17
            Dim li As New ListViewItem
            li.Text = My.Settings.All_BTCE_Names(x)
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.high))
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.low))
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.avg))
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.vol))
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.vol_cur))
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.last))
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.buy))
            li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.sell))
            li.SubItems.Add(ObjToDate(tskGet_BTCE(x).Result.updated).ToString)
            li.SubItems.Add(ObjToDate(tskGet_BTCE(x).Result.server_time).ToString)
            Me.ListView1.Items.Add(li)
        Next
    End Sub

    Function GetTradeData() As Trades.TradeData
        Dim retval As New Trades.TradeData
        retval = CoreProcedures.GetHttpData(CurrentTradeDataURL, Nothing, CoreProcedures.MethodType.GET)
        Return retval
    End Function

I want to be change the function to look like

 GetTradeData(CurrentTradeDataURL As String)

and pass the string to it directly. I understand that it's impossible to do w/o a Lambda expression, but have no idea how to do this in VB.Net.

MC9000
  • 2,076
  • 7
  • 45
  • 80

1 Answers1

0

Ok - got it figured out (I found the syntax for a Sub() expression and changed it to a function) - I left in the "old way" for reference:

'Public CurrentTradeDataURL As String = String.Empty

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim tskGet_BTCE As Task(Of Trades.TradeData)() = New Task(Of Trades.TradeData)(17) {}
    For i As Integer = 0 To 17
        ' CurrentTradeDataURL = My.Settings.All_BTCE_URIs(i)
        'tskGet_BTCE(i) = Task.Factory.StartNew(Of Trades.TradeData)(AddressOf GetTradeData)

        Dim uri As String = My.Settings.All_BTCE_URIs(i)
        tskGet_BTCE(i) = Task.Factory.StartNew(Function() As Trades.TradeData
                                                   Return GetTradeData(uri)
                                               End Function)

    Next

    Task.WaitAll(tskGet_BTCE)

    For x As Integer = 0 To 17
        Dim li As New ListViewItem
        li.Text = My.Settings.All_BTCE_Names(x)
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.high))
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.low))
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.avg))
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.vol))
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.vol_cur))
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.last))
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.buy))
        li.SubItems.Add(ObjToStr(tskGet_BTCE(x).Result.sell))
        li.SubItems.Add(ObjToDate(tskGet_BTCE(x).Result.updated).ToString)
        li.SubItems.Add(ObjToDate(tskGet_BTCE(x).Result.server_time).ToString)
        Me.ListView1.Items.Add(li)
    Next
End Sub

Function GetTradeData(CurrentTradeDataURL As String) As Trades.TradeData
    Dim retval As New Trades.TradeData
    retval = CoreProcedures.GetHttpData(CurrentTradeDataURL, Nothing, CoreProcedures.MethodType.GET)
    Return retval
End Function

in VB.Net, the syntax is not convert-able to C# by tools (or vice versa), so I hope this helps. It was easier than I thought.

MC9000
  • 2,076
  • 7
  • 45
  • 80
  • 1
    Did you mean `Await Task.WhenAll`? Otherwise, your UI is blocked until all tasks have been complete. – noseratio Jan 29 '14 at 08:03
  • I just now realized the UI locks up. In this case, it's locked up for 1 second, better than the 18 seconds before. I'll look into the "WhenAll" and see if I can avoid locking the UI at all. – MC9000 Jan 29 '14 at 10:14
  • I added async to the sub and replaced task.waitall(tskGet_BTCE) with Await Task.WhenAll(tskGet_BTCE) – MC9000 Jan 29 '14 at 10:24
  • NP, note also that you should consider disabling the button while you operation is still pending. Otherwise, the user may click it again and re-enter `Button1_Click`. More on this here: http://stackoverflow.com/a/21357567/1768303. – noseratio Jan 29 '14 at 10:46
  • Definitely, this is a prototype - the code will ultimately be in a separate dll. Thanks! – MC9000 Jan 31 '14 at 13:20