I am currently trying to pass progress (Using Iprogress and Progress) from a inner function to the main function. Everything works after the inner function completes. However, I am retrieving/downloading some data using EBay’s API’s (EBay’s finding service which is an rest service that returns data in XML format) and need to pass progress reports from the inner function to the main one during the download of the XML data retrieved/data processing.
Here’s the main function’s code (A little starting to get overloaded but you get whats going on. commented for sanity.):
Private Property a As Integer
Get
Return a_value
End Get
Set(value As Integer)
a_value = value
' ReportProgress(value, Nothing)
End Set
End Property
Private a_value As Integer
Public Async Function EvaluateItem(item As List(Of ItemInfo), evalprogress As IProgress(Of Integer), Optional ManualEvaluation As Boolean = False) As Task(Of List(Of EvaluationInfo))
Dim notevaluatedcount As Integer = 0
Dim iteminfo1 As ItemInfo = New ItemInfo
Dim tmpiteminfo As List(Of ItemInfo) = New List(Of ItemInfo)
Dim tmpiteminfo2 As List(Of ItemInfo) = New List(Of ItemInfo)
Dim pricefunctions As ItemValuation = New ItemValuation
Dim tmpevalinfo As EvaluationInfo = New EvaluationInfo
Dim itemevalresultarr As List(Of EvaluationInfo) = New List(Of EvaluationInfo)
Dim mode As Double
Dim avg As Double
Dim min As Double
Dim max As Double
Dim standarddev As Double
Dim pricearr() As Double
Dim autoitem As List(Of EvaluationInfo) = New List(Of EvaluationInfo)
Dim itemse As New ItemInformation
' Dim itemsnoteval As New ItemInformation
' itemseval.itemsevaluated = New List(Of String)
' itemsnoteval.notevaluated = New List(Of String)
Dim tmpnoteval As List(Of ItemInfo) = New List(Of ItemInfo)
Dim ran As Boolean
'sort and store item condition information in evaluation table in database or by item.sort
If item.Count > 1 And ManualEvaluation = True Then
tmpiteminfo = SortByName(item)
Await ClearEvalTable()
tmpiteminfo2 = SortByCondition(tmpiteminfo)
If CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess Then
Await Task.Run(Function()
'Await Task.Delay(1000)
If evalprogress IsNot Nothing Then
'ReportProgress(4, Nothing)
evalprogress.Report(4)
evalprogress.Report(5)
End If
' tempCount += 1
Return 5
End Function)
ElseIf CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess = False Then
Await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Function()
'Await Task.Delay(1000)
If evalprogress IsNot Nothing Then
evalprogress.Report(4)
evalprogress.Report(5)
End If
' tempCount += 1
Return 5
End Function)
End If
'evalprogress.Report(5)
' MsgBox("condition count:" + tmpiteminfo2.Count.ToString)
ElseIf item.Count > 1 And ManualEvaluation = False Then
'do nothing
ElseIf item.Count = 1 And ManualEvaluation = True Then
'change this code to perform manual evaluation on one item.
'tmpiteminfo.Add(item.Item(0))
End If
ReDim pricearr(item.Count)
If ManualEvaluation Then
If ran = False Then
Dim count As Integer
For Each d As ItemInfo In tmpiteminfo
count = count + 1
If ItemValidation.ContainsValidCharacters(d.name) And ItemValidation.IsDouble(d.price) Then
'decide whether to manually evaluate the item or automatically evaluate it.
Log("Item name: " + d.name + " price #: " + d.price.ToString)
Else
Log("Item: " + d.name + " has invalid characters in its name. It will not be evaluated. Please remove the invalid characters to have the item evaluated." + "The item price may not be an integer. please fix this too (if applicable)")
iteminfo1.name = d.name
iteminfo1.price = 0
iteminfo1.evaluationSource = d.evaluationSource
iteminfo1.damaged = "NO"
iteminfo1.aquisitiondate = "1/1/1111"
iteminfo1.itempicture = Nothing
' tmpnoteval.Add(iteminfo1)
tmpevalinfo.currentItem = iteminfo1.name
tmpevalinfo.evaluated = False
tmpevalinfo.evaluationcondition = d.itemcondition
itemevalresultarr.Add(tmpevalinfo)
' tmpnoteval.Add(iteminfo1)
notevaluatedcount += 1
End If
Select Case d.itemcondition
Case Is = ItemCondition.Broken
broken.Add(d.price)
Case Is = ItemCondition.LooksLikeNew
Lookslikenew.Add(d.price)
'MsgBox("Looks like new price:" + d.price.ToString)
Case Is = ItemCondition.SomewhatUsed
somewhatused.Add(d.price)
' MsgBox("Somewhat Used price:" + d.price.ToString)
Case Is = ItemCondition.SomeDamage
damaged.Add(d.price)
End Select
Next
ran = True
End If
Else
'Automatically evaluate item using different retailers i.e. Amazon, E-Bay, etc.
'use grabfromonlinesource multiple times to grab from each evaluation source used.
Dim tmpevalitem As Task(Of List(Of EvaluationInfo))
For i = 0 To item.Count - 1
'does once for each item
'need to split it into conditions inside of grabfromonlinesource
If ItemValidation.ContainsValidCharacters(item.Item(i).name) Then
' evalprogress = New Progress(Of Integer)(Function(value) InlineAssignHelper(value, a))
If CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess Then
Await Task.Run(Function()
'Await Task.Delay(1000)
If evalprogress IsNot Nothing Then
' ReportProgress(10, Nothing)
evalprogress.Report(10)
ReportProgress(10, Nothing)
End If
' tempCount += 1
Return 10
End Function)
ElseIf CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess = False Then
Await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Function()
'Await Task.Delay(1000)
If evalprogress IsNot Nothing Then
evalprogress.Report(10)
End If
' tempCount += 1
Return 10
End Function)
End If
tmpevalitem = GrabFromOnlineSource(item.Item(i).name, item.Item(i).evaluationSource, New Progress(Of Integer)(Function(value) InlineAssignHelper(a, value)))
tmpevalitem.Wait()
If CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess Then
Await Task.Run(Function()
'Await Task.Delay(1000)
If evalprogress IsNot Nothing Then
' ReportProgress(70, Nothing)
evalprogress.Report(70)
End If
' tempCount += 1
Return 70
End Function)
ElseIf CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess = False Then
Await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Function()
'Await Task.Delay(1000)
If evalprogress IsNot Nothing Then
'evalprogress.Report(70)
End If
' tempCount += 1
Return 70
End Function)
End If
' ItemValuation.tmpProgressIndicator.Report(60)
If tmpevalitem.Result IsNot Nothing Then
autoitem.AddRange(tmpevalitem.Result)
Else
Continue For
End If
Else
Dim tmpevalinfoauto As EvaluationInfo
tmpevalinfoauto.currentItem = item.Item(i).name
tmpevalinfoauto.evaluationcondition = item.Item(i).itemcondition
autoitem.Add(tmpevalinfoauto)
End If
Next i
autoitem.Add(Nothing) 'use nothing as an indicator of a new item.
End If
If ManualEvaluation Then
Dim done(4) As Boolean
done(0) = False
done(1) = False
done(2) = False
done(3) = False
'MsgBox("item information count: " + tmpiteminfo2.Count.ToString)
For f = 0 To tmpiteminfo2.Count - 1
'MsgBox(tmpiteminfo2.Item(f).evaluationSource)
Select Case tmpiteminfo2.Item(f).evaluationSource
Case Is = "Gamestop"
tmpevalinfo.valuationsourceid = 1
Case Is = "Amazon"
tmpevalinfo.valuationsourceid = 2
Case Is = "Ebay"
tmpevalinfo.valuationsourceid = 3
'add more sources here later
End Select
Select Case tmpiteminfo2.Item(f).itemcondition
Case Is = ItemCondition.Broken
'If done(0) = False Then
mode = pricefunctions.Mode(broken.ToArray)
max = pricefunctions.MaxValue(broken.ToArray)
min = pricefunctions.MinValue(broken.ToArray)
avg = pricefunctions.AveragePrice(broken.ToArray)
standarddev = pricefunctions.standarddeviation(broken.ToArray)
done(0) = True
' End If
Case Is = ItemCondition.LooksLikeNew
'If done(1) = False Then
mode = pricefunctions.Mode(Lookslikenew.ToArray)
max = pricefunctions.MaxValue(Lookslikenew.ToArray)
min = pricefunctions.MinValue(Lookslikenew.ToArray)
avg = pricefunctions.AveragePrice(Lookslikenew.ToArray)
standarddev = pricefunctions.standarddeviation(Lookslikenew.ToArray)
done(1) = True
' End If
Case Is = ItemCondition.SomeDamage
' If done(2) = False Then
mode = pricefunctions.Mode(damaged.ToArray)
max = pricefunctions.MaxValue(damaged.ToArray)
min = pricefunctions.MinValue(damaged.ToArray)
avg = pricefunctions.AveragePrice(damaged.ToArray)
standarddev = pricefunctions.standarddeviation(damaged.ToArray)
done(2) = True
' End If
Case Is = ItemCondition.SomewhatUsed
'If done(3) = False Then
mode = pricefunctions.Mode(somewhatused.ToArray)
max = pricefunctions.MaxValue(somewhatused.ToArray)
min = pricefunctions.MinValue(somewhatused.ToArray)
avg = pricefunctions.AveragePrice(somewhatused.ToArray)
standarddev = pricefunctions.standarddeviation(somewhatused.ToArray)
done(3) = True
' End If
End Select
'assign values to minimum price, maximum price, and the other prices.
If min > 0 Then
tmpevalinfo.MinimumPrice = min
End If
If mode > 0 Then
tmpevalinfo.ReoccuringPrice = mode
End If
If avg > 0 Then
tmpevalinfo.avgprice = avg
End If
If max > 0 Then
tmpevalinfo.MaximumPrice = max
End If
If standarddev > 0 Then 'And standarddev < 1 Then
tmpevalinfo.avgdeviation = standarddev
End If
min = 0
max = 0
mode = 0
avg = 0
tmpevalinfo.currentItem = tmpiteminfo2.Item(f).name
tmpevalinfo.evaluationcondition = tmpiteminfo2.Item(f).itemcondition
'MsgBox(tmpiteminfo2.Item(f).itemcondition)
tmpevalinfo.evaluated = True
itemevalresultarr.Add(tmpevalinfo)
Next f
'Dim iteminfoc As New ItemInformation
'For s = 0 To tmpiteminfo.Count - 1
' iteminfoc.itemsevaluate.Add(tmpiteminfo.Item(s).name)
' 'add other item information and change to iteminfo type once I get information to display correctly on findquote form
'Next s
Dim itemval As New ItemValuation
Dim tmpevalsource As New EvaluationSource
Using uie As New DataAccess.SQLiteDb
For h = 0 To tmpiteminfo.Count - 1
tmpevalsource.EvaluationSourceName = tmpiteminfo.Item(h).evaluationSource
tmpevalsource.EvaluationWebAddress = (From EvalWeb In uie.ValuationSources Where EvalWeb.ValuationSourceName = tmpevalsource.EvaluationSourceName Select EvalWeb).ToString
Await itemval.archiveitem(tmpiteminfo.Item(h).name, tmpiteminfo.Item(h).name, tmpevalsource)
Next
End Using
'delete all the evaluated items from the database for next evaluation
Await ClearEvalTable()
'return regular results
Return itemevalresultarr
Else
'return automated evaluation results
'results are archived as they are retrieved so delete data from the table below
'delete all the evaluated items from the database for next evaluation
Return autoitem
End If
End Function
Here’s the inner function’s signature:
Private Async Function GrabFromOnlineSource(itemname As String, WebsiteSource As String, progress As IProgress(Of Integer)) As Task(Of List(Of EvaluationInfo))
Here’s what I have tried so far (updated):
first try:
tmpevalitem = Await GrabFromOnlineSource(item.Item(i).name, item.Item(i).evaluationSource, New Progress(Of Integer)(Function(value) InlineAssignHelper(totalprogress, value))). 'replace totalprogress with the a integer I mentioned in the comments.
tmpevalitem.Wait()
second try:
tmpevalitem = GrabFromOnlineSource(item.Item(i).name, item.Item(i).evaluationSource, New Progress(Of IProgress(Of Integer))(Function(value) InlineAssignHelper(evalprogress, value)))
tmpevalitem.Wait()
The above code though ends up in an error about data type progress not being correct. I really need to pass my progress from GrabFromOnlineSource to the evalprogress variable or otherwise I will have differing values sent to the main program.
Note: I technically could have GrabFromOnlineSource called for each evaluation source used (4 total possible as of this moment). In addition, each evaluation source sent to GrabFromOnlineSource has its own progress reported counted toward the current evaluation source (i.e. ebay has its own progress, amazon its own, etc).
The EvaluationInfo and ItemInfo Structures:
Public Structure EvaluationInfo
Dim ReoccuringPrice As Double
Dim MinimumPrice As Double
Dim MaximumPrice As Double
Dim avgprice As Double
Dim avgdeviation As Double
Dim currentItem As String
Dim valuationsourceid As Integer
Dim evaluationcondition As ItemCondition 'i.e. used,new,broken enum
Dim evaluated As Boolean
End Structure
Public Structure ItemInfo
Public Property name As String
Public Property price As Double
Public Property damaged As String
Public Property aquisitiondate As Date
Public Property evaluationSource As String
Public Property itemcondition As ItemCondition
Public Property itempicture As Byte()
Public Property itemid As Integer
End Structure
More Information:
One thing I forgot to mention progress reporting does work with task.run from evaluateitem function but I prefer to modularize my code a bit to prevent one action from taking too much space and that’s why I have not moved the code from GrabFromOnlineSource into evaluateitem.
2
Answers
Sorry for the delay in answering my own question but here goes (I am not perfect at formatting code so an editor or admin can pretty it up):
This is the class test code I used separately from my projects dll to test this was working (aka I created a new project to test my theory):
Another thing that changed inside my main function was my while loop was a little wrong. I needed put in delays in-between passing progress reports back or else it did not pass it back or showed it at 100% at the end making my progress report useless. Anyone can still comment on best how to do this. Its a crazy thing that forgoting delays can mess up a program!
Everything else is pretty much the same. Except I put delays as above to have it stop passing progress long enough for the natural eye to see the progress happening.
have u try declarated one variable in function GrabFromOnlineSource as byref and pass to this method. after u modality in GrabFromOnlineSource u can observe this variable from main function or anny other place.
Sorry i should check that
Method nr.2
So why u dont wrap this process in class, something like that if u wanna progress in 2 task, u can always observe this object or add event for progress tracking