How do I use continueWith to continue a task with another task? - vb.net

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))

Related

How to do something on

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.

Runtime Generated EventHandler of Unknown Type

Ok, so I have been stuck on this for a while, combining various question solutions from on here.
Situation:
I instantiate an Object of Type x by using the activator.CreateInstance(x)
Type x can vary but always has the same properties and methods.
The problem is that type x has an event ReadCompleted as ReadCompleted (this is a delegate), type y has the same event, with the same delegate but it is of type ReadCompleted1, z => ReadCompleted2, etc...
Solution:
I assign a delegate at runtime using the following code:
Dim Client As Object = ServiceProvider.GetService(TypeDict(Entity))
Dim TaskCompletionSource As New TaskCompletionSource(Of Entity)()
Dim addMethod As MethodInfo = Client.GetType().GetMethod("add_ReadCompleted")
Dim removeMethod As MethodInfo = Client.GetType().GetMethod("remove_ReadCompleted")
Dim self As Object = Nothing
Dim getSelf As Func(Of Object) = Function() self
Dim eventArgType As Type = Client.GetType().GetEvent("ReadCompleted").EventHandlerType.GetMethod("Invoke").GetParameters()(1).ParameterType
Dim e As ParameterExpression = Expression.Variable(eventArgType)
Dim ExpBlock As BlockExpression = Expression.Block({Expression.Parameter(GetType(Object)), e},
Expression.Call(
Nothing,
Me.GetType().GetMethod("ProcessTask"),
Expression.Convert(e, eventArgType),
Expression.Constant(TaskCompletionSource)),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
)
)
Dim lambda As LambdaExpression = Expression.Lambda(
addMethod.GetParameters()(0).ParameterType,
ExpBlock,
Expression.Parameter(GetType(Object)),
Expression.Parameter(eventArgType))
Dim dlg As [Delegate] = lambda.Compile()
self = dlg
addMethod.Invoke(Client, {dlg})
Client.ReadAsync(PrimaryKey)
Now my knowledge on linq and it's Expression class is limited and i did my best to research the msdn documentation but i can't figure it out:
the method ProcessTask gets called properly, for which i've worked long enough, but my parameter e is always Nothing, resulting in a NullReferenceException.
The method:
Public Shared Sub ProcessTask(ByVal e, ByRef tcs)
'Console.WriteLine(e.GetType())
If e.Error IsNot Nothing Then
tcs.TrySetException(e.Error)
ElseIf e.Cancelled Then
tcs.TrySetCanceled()
Else
tcs.TrySetResult(e.Result)
End If
End Sub
I have no idea why, according to how i see it this is the correct way to call my method, but obviously it isn't. Can someone point me in the right direction for this?
Could be I'm just plain blind and missing something very obvious....
Thanks in advance!
EDIT:
Whilst awaiting an answer i tried to do some more debugging(which is hell in this scenario) saw that if i do:
Dim s As ParameterExpression = Expression.Variable(GetType(Object), "Sender")
Dim ExpBlock As BlockExpression = Expression.Block({s, e},
Expression.Call(
Nothing,
GetType(Console).GetMethod("WriteLine", New Type() {GetType(String)}),
Expression.Call(s, GetType(Object).GetMethod("ToString"))),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
))
The sender as object parameter is also nothing, so i'm getting the feeling that none of my arguments are getting passed through...
Hope this helps shed more light on the matter.
I figured it out, turns out i misinterpreted the whole parameter thing of Expression:
Dim Client As Object = ServiceProvider.GetService(TypeDict(Entity))
Dim TaskCompletionSource As New TaskCompletionSource(Of Entity)()
Dim addMethod As MethodInfo = Client.GetType().GetMethod("add_ReadCompleted")
Dim removeMethod As MethodInfo = Client.GetType().GetMethod("remove_ReadCompleted")
Dim self As Object = Nothing
Dim getSelf As Func(Of Object) = Function() self
Dim eventArgType As Type = Client.GetType().GetEvent("ReadCompleted").EventHandlerType.GetMethod("Invoke").GetParameters()(1).ParameterType
Dim s As ParameterExpression = Expression.Parameter(GetType(Object), "Sender")
Dim e As ParameterExpression = Expression.Variable(eventArgType, "EventArgs")
Dim ExpBlock As BlockExpression = Expression.Block(\*{Expression.Parameter('GetType(Object)), e},*\ <--- this has to go
Expression.Call(
Nothing,
Me.GetType().GetMethod("ProcessTask"),
Expression.Convert(e, eventArgType),
Expression.Constant(TaskCompletionSource)),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
)
)
Dim lambda As LambdaExpression = Expression.Lambda(
addMethod.GetParameters()(0).ParameterType,
ExpBlock,
s,
e)
\*Expression.Parameter(GetType(Object)),
Expression.Parameter(eventArgType))*\ <-- this has to change
Dim dlg As [Delegate] = lambda.Compile()
self = dlg
addMethod.Invoke(Client, {dlg})
Client.ReadAsync(PrimaryKey)
So as i see it the parameters don't have to be defined in the expression itself, but they sould be created, and the reference should be kept to use them in the lambda in which you compile the expression.
Hope someone in the future has some use for this answer, and thanks to all for taking a look at this.

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.

setting strings_array(0) = "" problem

im getting an exception on this:
Dim strings_extreme As String()
strings_extreme(0) = ""
it says that i am using it before it is being assigned a value
how do i initialize it?
please note that i need to be able to do this:
strings_extreme = input.Split(","c).Distinct().OrderBy(Function(s) s)
If you truly don't know how many strings there are going to be, then why not just use an IList:
Dim stringList As IList(Of String) = New List(Of String)
stringList.Add("")
You can get the Count of how many strings there are and you can For Each through all the strings in the list.
EDIT: If you're just trying to build an array from a Split you should be able to do this:
Dim strings_extreme() As String = input.Split(...)
Dim strings_extreme As List(Of String) = New List(Of String)
strings_extreme.Add("value1")
strings_extreme.Add("value 2")
strings_extreme.Add("value 3rd")
strings_extreme.Add("value again")
Dim strings() As String = strings_extreme.ToArray()
...
Dim strings_extreme(10) As String
strings_extreme(0) = ""
Further info: http://www.startvbdotnet.com/language/arrays.aspx
Dim strings_extreme as String() = {"yourfirstitem"}
But actually, why not take a look at some more advanced data structure from System.Collections namespace?
Shouldn't bother setting a string to "".
Try using:
Dim strings_extreme(10) As String
strings_extreme(yourIndex) = String.Empty