How to do something on - vb.net

Public Shared Async Function getMarketDetailFromAllExchangesAsync() As Task
Dim taskList = New List(Of Task)
For Each account In uniqueAccounts()
Dim newtask = account.Value.getMarketInfoAsync()
taskList.Add(newtask)
Next
Await Task.WhenAll(taskList.ToArray)
Dim b = 1
End Function
The code work just fine.
However, I want to log every time a task is done
So I did
newtask.ContinueWith(Async Function(x) LogEvents(account.ToString))
LogEvents is a normal function. I got 2 error
How exactly should I do that?

I did it this way
Public Shared Async Function getMarketDetailFromAllExchangesAsync() As Task
Dim taskList = New List(Of Task)
Dim starttime = jsonHelper.currentTimeStamp
LogEvents("Start Getting Market Detail of All")
For Each account In uniqueAccounts().Values
Dim newtask = account.getMarketInfoAsync().ContinueWith(Sub() account.LogFinishTask("GetMarketDetail", starttime))
taskList.Add(newtask)
'newtask.ContinueWith(Sub() LogEvents(account.ToString))
Next
Await Task.WhenAll(taskList.ToArray)
Dim b = 1
End Function
If anyone knows how to do so without a lambda that'll be great.

Related

How do I use continueWith to continue a task with another task?

Dim listOfTask = New List(Of Task)
For Each account In uniqueAccounts().Values
Dim newtask = account.conditionalInitializeAsync()
Dim nexttask = account.getPairsPriceStepAsync()
listOfTask.Add(newtask)
listOfTask.Add(nexttask)
Dim nexttaskaftenewtask = newtask.ContinueWith(nexttask) 'compiler warning
Next
Instead of list
listOfTask.Add(newtask)
listOfTask.Add(nexttask)
I want to do
listOfTask.Add(nexttaskaftenewtask )
How do I do so?
I can compile the following without error or warning. Hope this helps.
Dim nexttaskaftenewtask = newtask.ContinueWith(New Action(Of Task)(Function() nexttask))

How to do this without lambda?

Public Shared Async Function getMarketDetailFromAllExchangesAsync() As Task
Dim taskList = New List(Of Task)
Dim starttime = jsonHelper.currentTimeStamp
LogEvents("Start Getting Market Detail of All")
For Each account In uniqueAccounts().Values
Dim newtask = account.getMarketInfoAsync().ContinueWith(Sub() account.LogFinishTask("GetMarketDetail", starttime))
taskList.Add(newtask)
'newtask.ContinueWith(Sub() LogEvents(account.ToString))
Next
Await Task.WhenAll(taskList.ToArray)
Dim b = 1
End Function
Is there a way to do .ContinueWith(Sub() account.LogFinishTask("GetMarketDetail", starttime)) with addressOf instead?
How?
You need to create a method which satisfies any of existed ContinueWith overloads.
In your particular case it should satisfy a signature of Action(Of Task).
But because in ConitnuesWith you are using account instance, you will not be able to use AddressOf with method of the class where loop is executed.
As workaround you can create required method in class of account
Public Class Account
Public Sub LogFinishedMarketDetail(task As Task)
Dim starttime = jsonHelper.currentTimeStamp
Me.LogFinishTask("GetMarketDetail, starttime")
End Sub
End Class
Usage
For Each account In uniqueAccounts().Values
Dim newtask =
account.getMarketInfoAsync().ContinueWith(AddressOf account.LogFinishedMarketDetail)
taskList.Add(newtask)
Next
Suggestion - set Option Strict to On - will saves developer time by displaying possibly errors during compile time, instead of run-time.

Waiting for all Tasks in Async to complete

I am trying to run 10 processes simultaneously and when they finish I want to display a messagebox. The UI should remain responsive.
I have this function (MultiProcessImages) which displays a message before all the images finish:
'Start multi processing of images
Public Shared Async Function MultiProcessImages() As Task
'Create a task factory and add 10 process one for each ending image number
Dim t As Task = Nothing
For i As Integer = 0 To 9
Dim temp_i As Integer = i
t = Task.Factory.StartNew(Function() Cheque.CopyBinaryValueToFile(temp_i))
Await t
Next
End Function
Then I created another function which makes the UI unresponsive and also the processing does not seem to be multitasking (which means it does not perform all the actions of the CopyBinaryValueToFile in parallel but only for each task number):
Public Shared Async Function MultiProcessImages**2**() As Task
Dim tasks As New List(Of Task)()
For i As Integer = 0 To 9
Dim temp_i As Integer = i
tasks.Add(Cheque.CopyBinaryValueToFile(temp_i))
' tasks.Add(Task.Factory.StartNew(Function() Cheque.CopyBinaryValueToFile(temp_i)))
Next
Await Task.WhenAll(tasks)
MessageBox.Show("done")
End Function
Any ideas how to make it behave like I have it in the first function but wait until all the processes finish to display a message?
EDIT
I'm calling the function like this:
Private Async Sub cmdConvert_Click(sender As Object, e As EventArgs) Handles cmdConvert.Click
'Await Cheque.CopyBinaryValueToFile()
'{Time count
Dim start_time As DateTime
Dim stop_time As DateTime
Dim elapsed_time As TimeSpan
start_time = Now
'}
Await Cheque.MultiProcessImages2()
'{Time count
stop_time = Now
elapsed_time = stop_time.Subtract(start_time)
MessageBox.Show("elapsed_time = " & stop_time.Subtract(start_time).ToString & Environment.NewLine _
& elapsed_time.TotalSeconds.ToString("0.000000"))
'}
End Sub
Without seeing the rest of your code and the implementation of Cheque.CopyBinaryValueToFile(), the following may help you resolve the issue of UI being blocked:
Within MultiProcessImages2():
tasks.Add(Task.Run(Function() Cheque.CopyBinaryValueToFile(temp_i)))

vb.net - How to Declare new task as SUB with parameters

As you know we have a new syntax in vb.net with possibility to create inline tasks so we could run it asynchronously.
This is the correct code:
Dim testDeclaring As New Task(Sub()
End Sub)
testDeclaring.Start()
but now I need to pass a parameter in the subroutine and I can't find correct syntax for that.
Is it possible any way?
It's not possible. However, you could just use the parameters from the current scope:
Public Function SomeFunction()
Dim somevariable as Integer = 5
Dim testDeclaring As New Task(Sub()
Dim sum as integer = somevariable + 1 ' No problems here, sum will be 6
End Sub)
testDeclaring.Start()
End Function
If you want to pass a parameter you could do this
Dim someAction As Action(Of Object) = Sub(s As Object)
Debug.WriteLine(DirectCast(s, String))
End Sub
Dim testDeclaring As New Task(someAction, "tryme")
testDeclaring.Start()
Dont know if you looking for this:
Dim t As Task = New Task(Sub() RemoveBreakPages(doc))
Sub RemoveBreakPages(ByRef doc As Document)
Dim paragraphs As NodeCollection = doc.GetChildNodes(NodeType.Paragraph, True)
Dim runs As NodeCollection = doc.GetChildNodes(NodeType.Run, True)
For Each p In paragraphs
If CType(p, Paragraph).ParagraphFormat().PageBreakBefore() Then
CType(p, Paragraph).ParagraphFormat().PageBreakBefore = False
End If
Next
End Sub
Regards.

Strange error reported in this code, please explain?

I put together this bit of code from a few other samples, and I am getting an error I cant understand. On this line in the code below, on the word Observer,
Dim Results As ManagementObjectCollection = Worker.Get(Observer)
I get the error
"Value of type 'System.Management.ManagementOperationObserver' cannot be converted to 'Integer'"
Can somebody explain what this means?
There are two signatures for ManagementObjectSearcher.Get(), one has no parameters and the other has one parameter, a ManagementOperationObserver for async operation. That is what I am providing, yet the error indicates conversion involving an integer?
Public Shared Sub WMIDriveDetectionASYNC(ByVal args As String())
Dim Observer As New ManagementOperationObserver()
Dim completionHandler As New MyHandler()
AddHandler Observer.Completed, AddressOf completionHandler.Done
Dim Machine = "192.168.0.15"
Dim Scope = New ManagementScope("\\" & Machine & "\root\cimv2")
Dim QueryString = "select Name, Size, FreeSpace from Win32_LogicalDisk where DriveType=3"
Dim Query = New ObjectQuery(QueryString)
Dim Worker = New ManagementObjectSearcher(Scope, Query)
Dim Results As ManagementObjectCollection = Worker.Get(Observer) 'use parameter to make async
For Each item As ManagementObject In Results
Console.WriteLine("{0} {2} {1}", item("Name"), item("FreeSpace"), item("Size"))
Dim FullSpace As Long = (CLng(item("Size")) - CLng(item("FreeSpace"))) \ 1000000
Console.WriteLine(FullSpace)
Next
End Sub
Public Class MyHandler
Private _isComplete As Boolean = False
Public Sub Done(sender As Object, e As CompletedEventArgs)
_isComplete = True
End Sub 'Done
Public ReadOnly Property IsComplete() As Boolean
Get
Return _isComplete
End Get
End Property
End Class
Thanks for any advice!
I think that uses a reference type to get the result and put it in the object you sent as a parameter. So I think it just needs to look like:
Worker.Get(Observer)
instead of trying to set something = to that since it isn't a function that returns a value.
Then use the events you hook up to the object to handle whatever you need to do with the items you find.