我目前正在尝试将内部函数的进度(使用Iprogress和Progress)传递给main函数。内部函数完成后,一切正常。但是,我正在使用EBay的API检索/下载一些数据(EBay的查找服务是一种以XML格式返回数据的休息服务),并且需要在下载检索的XML数据期间将进度报告从内部函数传递到主函数/数据处理。
这是主要功能的代码(有点开始变得过载,但你会得到什么。为了理智而评论。):
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
这是内部函数的签名:
Private Async Function GrabFromOnlineSource(itemname As String, WebsiteSource As String, progress As IProgress(Of Integer)) As Task(Of List(Of EvaluationInfo))
这是我到目前为止所尝试的内容(已更新):
首先尝试:
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()
第二次尝试:
tmpevalitem = GrabFromOnlineSource(item.Item(i).name, item.Item(i).evaluationSource, New Progress(Of IProgress(Of Integer))(Function(value) InlineAssignHelper(evalprogress, value)))
tmpevalitem.Wait()
上述代码虽然最终导致数据类型进度不正确的错误。我真的需要将我的进度从GrabFromOnlineSource传递给evalprogress变量,否则我会将不同的值发送到主程序。
注意:从技术上讲,我可以为每个使用的评估源调用GrabFromOnlineSource(截止到目前为止总共有4个)。此外,发送给GrabFromOnlineSource的每个评估源都有自己的进度报告计入当前评估源(即ebay有自己的进展,亚马逊有自己的进展等)。
EvaluationInfo和ItemInfo结构:
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
更多信息:
有一件事我忘了提及进度报告确实可以使用来自evaluateitem函数的task.run,但我更喜欢模块化我的代码以防止一个动作占用太多空间,这就是为什么我没有将代码从GrabFromOnlineSource移动到evaluateitem。
答案 0 :(得分:2)
你尝试在函数GrabFromOnlineSource中声明一个变量asref并传递给这个方法。在GrabFromOnlineSource中你的模态之后你可以从main函数或者其他地方观察这个变量。
抱歉,我应该检查
方法nr.2
那么为什么你不在课堂上包装这个过程,如果你想在2个任务中进步,你可以随时观察这个对象或为进度跟踪添加事件
Public Sub SomeMethod()
Dim Wrap1 As New WrapConteiner
Dim Wrap2 As New WrapConteiner
Wrap2.Sleep = 200
Dim Tasks(0 To 1) As Task
Tasks(0) = New Task(AddressOf Wrap1.AwaitedProcessAsync)
Tasks(1) = New Task(AddressOf Wrap2.AwaitedProcessAsync)
Tasks(0).Start()
Tasks(1).Start()
Do While (Tasks(0).Status = TaskStatus.Running Or Tasks(1).Status = TaskStatus.Running Or Tasks(0).Status = TaskStatus.WaitingToRun Or Tasks(1).Status = TaskStatus.WaitingToRun)
Task.WaitAll(Tasks, 10)
Debug.Print("Wrap1: " & Wrap1.Progress)
Debug.Print("Wrap2: " & Wrap2.Progress)
Loop
Debug.Print("B")
End Sub
Public Class WrapConteiner
Property Progress As Integer
Property Sleep As Integer = 100
Public Sub AwaitedProcessAsync()
Dim x As Integer
For x = 1 To 100
Me.Progress = x
Threading.Thread.Sleep(Sleep)
Next
End Sub
End Class
答案 1 :(得分:0)
对于延迟回答我自己的问题感到抱歉但是这里(我不是完美的格式代码,所以编辑或管理员可以把它搞砸了):
这是我在我的项目中单独使用的类测试代码,用于测试这是否有效(我创建了一个新项目来测试我的理论):
Imports Windows.ApplicationModel.Core
Imports Windows.UI.Core
Public Class Progresstestclass
Private Shared Property totalprogress As Integer
Public Shared Async Function MainFunction(progress As IProgress(Of Integer)) As Task(Of Boolean)
totalprogress = 5
progress.Report(totalprogress)
Dim a As New String("")
Do While totalprogress > 0 And totalprogress < 70 And a <> "Success"
Await InnerFunction(New Progress(Of Integer)(Function(value) InlineAssignHelper(totalprogress, value)))
progress.Report(totalprogress - 5)
Await System.Threading.Tasks.Task.Delay(1000)
progress.Report(totalprogress)
Loop
Return True
End Function
Private Shared Async Function InnerFunction(progress2 As IProgress(Of Integer)) As Task(Of String)
progress2.report(30)
Await System.Threading.Tasks.Task.Delay(1000)
progress2.Report(40)
Await System.Threading.Tasks.Task.Delay(1000)
Return "Success"
End Function
Public Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
End Class
我的主要功能内部改变的另一件事是我的while循环有点不对劲。我需要在传递进度报告之间加入延迟,否则它没有将其传回或在最后以100%显示,使我的进度报告无用。任何人仍然可以评论如何做到这一点。忘记延误会让计划陷入困境,这是一件疯狂的事情!
其他一切都差不多。除非我按照上面的延迟,让它停止通过足够长的时间以让自然的眼睛看到正在发生的进展。