Running .Net Tasks in parallel that return different objects - vb.net

I am currently looking at processing 2 data downloads from a WCF service that return collections of different objects and was wondering if there was a better method than running the two asynchronous tasks synchronously.
In this case can I implement as Task.WhenAll or Task.WhenAny methodology to run these tasks in parallel?
Public Property Users As IEnumerable(Of UserDto)
Get
Return _users
End Get
Set(value As IEnumerable(Of UserDto))
_users = value
RaisePropertyChanged("Users")
End Set
End Property
Public Property ApplicationRoles() As IEnumerable(Of ApplicationRoleDto)
Get
Return _roles
End Get
Set(ByVal value As IEnumerable(Of ApplicationRoleDto))
_roles = value
RaisePropertyChanged("ApplicationRoles")
End Set
End Property
Private Async Sub GetUserDetails()
Users = Await _serviceHelper.GetUsers()
ApplicationRoles = Await _serviceHelper.GetApplicationRoles
End Sub
Possible solution
I could use the Task Parrallel Library but I am not sure if this is the most efficient method, plus I can't await the return.
Parallel.Invoke(Sub() Users = _serviceHelper.GetUsers(),
Sub() ApplicationRoles = _serviceHelper.GetApplicationRoles())

Task.WhenAll should work just fine. Pardon if the syntax isn't quite correct; my VB is incredibly rusty:
Private Async Function GetUserDetailsAsync() As Task
Dim UsersTask = _serviceHelper.GetUsersAsync()
Dim ApplicationRolesTask = _serviceHelper.GetApplicationRolesAsync
Await Task.WhenAll(UsersTask, ApplicationRolesTask);
Users = Await UsersTask
ApplicationRoles = Await ApplicationRolesTask
End Function
I also took the liberty of changing your Sub to a Function (you should avoid Async Sub), and making your Async methods end with Async, as per the convention.

Related

VB - CefSharp not return values

I can fill a value of a specific field with the code below
nav.EvaluateScriptAsync("document.getElementById('email').value='teste';")
but I can't return the value of this field
Dim placeholder As Task(Of JavascriptResponse) = nav.EvaluateScriptAsync("document.getElementById('email').value")
Task.WaitAll()
MsgBox(placeholder.Result.ToString)
both (placeholder.Result.ToString) and (placeholder.ToString) return "CefSharp.JavascriptResponse"
You can obtain the value from JavascriptResponse.Result property. Check the Success property first, if the script evaluation failed the error will be contained with the Message property.
http://cefsharp.github.io/api/97.1.x/html/Properties_T_CefSharp_JavascriptResponse.htm
I got it that way.
Public Async Function testeAsync() As Task(Of String)
Dim placeholder2 As JavascriptResponse = Await nav.EvaluateScriptAsync("document.getElementById('email').placeholder")
If (placeholder2.Success) Then
MsgBox(placeholder2.Result)
End If
End Function
But when I do a return in the function and call the function in a struct, how do I call waiting for the async function to complete?
This way the sub prints the result before the asynchronous process ends.
Sub testeResultado()
Dim returnedTaskTResult As Task(Of String) = testeAsync()
MsgBox(returnedTaskTResult.ToString)
End Sub

Returning list in async function in uwa vb.net

I am trying to parse through some xml files and return the results to a datagrid in UWA. The code builds fine but when running it returns
Unable to cast object of type 'System.Threading.Tasks.Task1[System.Collections.Generic.List1[Festplatten_Archiv_Client.Drive]]' to type 'System.Collections.IEnumerable'.
In my XAML.vb I am only calling the class to create the files and set the results as fileSource:
Public Sub New()
InitializeComponent()
dataGrid.ItemsSource = Drive.Drives
End Sub
Which works fine if I only add a sample Drive with
drivelist.Add(New Drive("Name",0, 0, 0), "location", "date"))
But as I want to parse through the XMLs, this is my code.
This is my drives class:
Public Shared Async Function Drives() As Task(Of List(Of Drive))
Dim drivelist As New List(Of Drive)
Dim folderpicked As StorageFolder
Try
folderpicked = Await StorageApplicationPermissions.FutureAccessList.GetItemAsync(ReadSetting("folderStorageToken"))
Catch ex As Exception
Debug.WriteLine("Fehler: " & ex.Message)
folderpicked = Nothing
End Try
Dim xmlfiles As List(Of StorageFile) = Await folderpicked.GetFilesAsync()
For Each file In xmlfiles
''Process files
Next
Return Await Task.Run(Function() drivelist)
End Function
It might be something with async programming, but I am very new to this. Thanks for any help!
You can make a blocking call to an Async routine from the ctor as follows:
Dim drivesResult = Drives().GetAwaiter().GetResult()
This is effectively forcing the routine to execute synchronously. If that's not what you want, then you'll need to explore a different alternative, e.g. the suggestion in the comments.

VB.Net to optimize execution by keeping data other than fetching data from database everytime

I am newbie in vb.net I am trying to optimize my code execution that i am working on . i am working on a program having more than 45 forms. In every form its calling the function IsPowerUser to check is power user
If we can store all details about user while logging in , then we need to use these values every time when we needed instead of collecting data from database . May be this question belongs to VB Basics.
You can use lazy initialization to postpone the database call until you actually need the information (if ever), and then store the value for re-use.
Private _isPowerUser As New Lazy(Of Boolean)(AddressOf GetIsPowerUser)
Public Function IsPowerUser() As Boolean
Return _isPowerUser.Value
End Function
Private Function GetIsPowerUser() As Boolean
' Retrieve the information from the database and return
Return True Or False
End Function
In this sample, _isPowerUser is a backing field that uses lazy initialization. It is first initialized when someone calls IsPowerUser. Under the covers, Lazy(Of T) then calls the delegate GetIsPowerUser() that does all the heavy lifting to retrieve the value from the database.
Lazy(Of T) only needs to call GetIsPowerUser() once.
In other words: any consecutive calls to IsPowerUser() do not trigger GetIsPowerUser().
EDIT (1/2)
Lazy(Of T) was not introduced until .NET 4, so here is a code sample that works for .NET 2 and above:
Private _isPowerUser As Boolean?
Private lazyLock As New Object
Public Function IsPowerUser() As Boolean
If Not _isPowerUser.HasValue Then
SyncLock lazyLock
If Not _isPowerUser.HasValue Then
_isPowerUser = GetIsPowerUser()
End If
End SyncLock
End If
Return _isPowerUser.Value
End Function
Private Function GetIsPowerUser() As Boolean
' Retrieve the information from the database and return
Return True Or False
End Function
EDIT (2/2)
I changed my code sample to work in a multi-user environment:
Private _powerUsers As New Dictionary(Of Long, Boolean)
Private ReadOnly LazyLock As New Object
Public Function IsPowerUser(userId As Long) As Boolean
If Not _powerUsers.ContainsKey(userId) Then
SyncLock LazyLock
If Not _powerUsers.ContainsKey(userId) Then
_powerUsers.Add(userId, GetIsPowerUser(userId))
End If
End SyncLock
End If
Return _powerUsers.Item(userId)
End Function
Private Function GetIsPowerUser(UId As Long) As Boolean
' Retrieve the information from the database and return
Return True Or False
End Function
Usage example:
Dim Steven As Long = 454151
If IsPowerUser(Steven) Then
Console.WriteLine("Steven is a power user.")
Else
Console.WriteLine("Steven is a normal user.")
End If

Start task without waiting

I would like to start a background task without using the Await keyword. Instead I want to monitor the task at various points and restart it when necessary to update information in the background. Here is the method I am trying to call:
Public Async Function UpdateVehicleSummaries(p_vehicleID As Int32) As Task(Of Boolean)
Dim tempVehicle As Koolsoft.MARS.BusinessObjects.Vehicle
For Each tempVehicle In Vehicles
If p_vehicleID = 0 Or p_vehicleID = tempVehicle.VehicleID Then
Await UpdateVehicleStats(tempVehicle)
End If
Next
Return True
End Function
The code I am trying to start the task doesn't seem to work and I'm not sure how to provide the parameter. I get an error that "Task(Of Boolean) cannot be converted to System.Action and or an error on the parameter"
Dim tempTask As Task
tempTask = New Task(UpdateVehicleSummaries(tempVehicleID))
tempTask.Start()
Any help would be appreciated.
Since UpdateVehicleSummaries is already asynchronous, you should be abel to just do:
Dim tempTask As Task(Of Boolean) = UpdateVehicleSummaries(tempVehicleID)
The returned Task(Of T) will be "hot" (running), but shouldn't block, as the Await call will immediately return control flow to the caller at that point.
A more typical use of this method, if you need to perform other work while this runs, would be to do the following:
Dim tempTask = UpdateVehicleSummaries(tempVehicleID)
' Do your other work
Dim success = Await tempTask ' Get the boolean result asynchronously...
' use the result

Trying to get asynchronous functions with arguments and returns to work

I have been trying to get a function to work asynchronously with a GUI window, and having very limited success.
The code below is my function, XXX, with a delegate and Callback - to allow stopping the GUI thread, without getting an error.
It works though - if it is a Sub, not a function, and if it doesn't have any arguments.
I don't know how to change it so I can check its return value... I have found a little help in some examples, http://msdn.microsoft.com/en-us/library/system.iasyncresult.asyncstate.aspx - but they print the return value in the callback, and I can't see how to get it in the caller.
I can't find any way to use arguments in my function.
Private Function XXX_Callback(ByVal ia As IAsyncResult)
Dim d As XXXDelegate = CType(CType(ia, Runtime.Remoting.Messaging.AsyncResult).AsyncDelegate, XXXDelegate)
d.EndInvoke(ia)
Dim result As AsyncResult = CType(ia, AsyncResult)
Dim caller As XXXDelegate = CType(result.AsyncDelegate, XXXDelegate)
Dim returnValue As Boolean = caller.EndInvoke(ia)
XXX_Finish() ' needs the "vvv argument, I don't know how to get it
' The returnValue is here but I don't know how to send it to the caller
End Function
'Private Function XXX_Finish(ByVal vvv as Boolean) As Boolean
' this probably needs to return something, I don't know what/ how to get it
Private Function XXX_Finish() As Boolean
' something
myGui.Finish()
End Function
' Private Delegate Function XXXDelegate(ByVal vvv As Integer) As Boolean
' Public Function XXX(ByVal vvv As Integer) As Boolean ' This is what I would like
Private Delegate Sub XXXDelegate()
Public Sub XXX()
'
myGui.Update()
'
End Sub
Public Sub Caller()
'
myGui = New SomeGui()
myGui.Begin()
Dim t As New XXXDelegate(AddressOf XXX)
t.BeginInvoke(AddressOf XXX_Callback, Nothing)
' more code, another call
End Sub
Private myGui As SomeGui
Please, could someone help me get this into a better shape, or get some examples that will help ? With the ones I have found in the past two days, I have reached a dead end...
Thank you.
After searching through lots of posts on the web, and reading a couple of books, I have found the best resource, with examples for each case that one might encounter:
http://support.microsoft.com/kb/315582
The answers to this particular question are in the above link, "Sample 2: Calling A Method Asynchronously by Using the EndInvoke() Call Pattern" and "Sample 5: Executing a Callback When an Asynchronous Method Completes."
The best thing about it though is the simple and organized fashion in which the options to use Invoke, EndInvoke, Callback are explained.
One thing to note: for my question above, the essential breakthrough was when I read the words "BeginInvoke() returns immediately and does not wait for the asynchronous call to complete."
So... trying to call another method, after it, was the wrong approach.
This is how i made an asyncronous function calls.
I declare the function in the module.
Private Delegate Function fnBolAsyncCallVerificacionNuevaVersion(ByVal pIntModo As Integer, ByVal pIntAccion As Integer) As Boolean
Private Delegate Function fnBolAsyncCallActualizacionTipoCambio(ByVal pIntActualizacionMandatoria As clsBusinessBoxData.tblTipoCambio.enumActualizacionMandatoria) As typBolResultadoFuncion
The functions receive some parameters and the first returns a boolean and the second returns an structure with 2 data, one boolean and one string.
In the load event of the form I call the functions.
sAsyncVerificaVersion = New fnBolAsyncCallVerificacionNuevaVersion(AddressOf fnBolVerificaActualizacion)
sAsyncVerificaVersion.BeginInvoke(enumDisplayGUIMode.Silent, typApplicationUpdate.CheckOnly, New AsyncCallback(AddressOf fnBolTerminaVerificacionVersion), Nothing)
sAsyncActualizaTiposCambio = New fnBolAsyncCallActualizacionTipoCambio(AddressOf fnBolActualizaTiposCambioYahoo)
sAsyncActualizaTiposCambio.BeginInvoke(clsBusinessBoxData.tblTipoCambio.enumActualizacionMandatoria.No, New AsyncCallback(AddressOf fnBolTerminaActualizacionTipoCambio), Nothing)
These calls will execute the function asyncronous and will callback the function defined when finished.
Then i receive the results in the callback functions defined.
Private Function fnBolTerminaVerificacionVersion(ByVal pIarResultado As IAsyncResult) As Boolean
Dim sClsResultado = CType(pIarResultado, Messaging.AsyncResult)
Dim sIarResultado As fnBolAsyncCallVerificacionNuevaVersion = CType(sClsResultado.AsyncDelegate, fnBolAsyncCallVerificacionNuevaVersion)
Dim sBolExisteNuevaVersion As Boolean = False
CheckForIllegalCrossThreadCalls = False
sBolExisteNuevaVersion = sIarResultado.EndInvoke(pIarResultado)
mnuBajarActualizacion.Enabled = sBolExisteNuevaVersion
CheckForIllegalCrossThreadCalls = True
Return True
End Function
Private Function fnBolTerminaActualizacionTipoCambio(ByVal pIarResultado As IAsyncResult) As Boolean
Dim sBolActualizacionExitosa As typBolResultadoFuncion
Dim sClsResultado = CType(pIarResultado, Messaging.AsyncResult)
Dim sIarResultado As fnBolAsyncCallActualizacionTipoCambio = CType(sClsResultado.AsyncDelegate, fnBolAsyncCallActualizacionTipoCambio)
CheckForIllegalCrossThreadCalls = False
sBolActualizacionExitosa = sIarResultado.EndInvoke(pIarResultado)
CheckForIllegalCrossThreadCalls = True
Return True
End Function
I hope they help.