visual ventana tareas tarea sirve segundo que progreso plano para net hilos espera ejemplo ejecutar con barra bar vb.net uwp uwp-xaml progress

vb.net - ventana - tareas en segundo plano vb net



¿Cómo pasar informes de progreso de la función interna a la función principal? (2)

Actualmente estoy tratando de pasar el progreso (usando Iprogress y Progress) de una función interna a la función principal. Todo funciona después de que la función interna se completa. Sin embargo, estoy recuperando / descargando algunos datos usando las API de EBay (servicio de búsqueda de eBay que es un servicio de descanso que devuelve datos en formato XML) y necesito pasar informes de progreso de la función interna a la principal durante la descarga de los datos XML recuperados /procesamiento de datos.

Aquí está el código de la función principal (un poco comienza a sobrecargarse, pero usted sabe lo que está pasando, comentó sobre la sensatez):

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

Aquí está la firma de la función interna:

Private Async Function GrabFromOnlineSource(itemname As String, WebsiteSource As String, progress As IProgress(Of Integer)) As Task(Of List(Of EvaluationInfo))

Esto es lo que he intentado hasta ahora ( actualizado ):

primer intento:

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

segundo intento:

tmpevalitem = GrabFromOnlineSource(item.Item(i).name, item.Item(i).evaluationSource, New Progress(Of IProgress(Of Integer))(Function(value) InlineAssignHelper(evalprogress, value))) tmpevalitem.Wait()

El código anterior termina en un error sobre el progreso del tipo de datos que no es correcto. Realmente necesito pasar mi progreso de GrabFromOnlineSource a la variable evalprogress o de lo contrario tendré diferentes valores enviados al programa principal.

Nota: técnicamente podría tener GrabFromOnlineSource llamado para cada fuente de evaluación utilizada (4 totales posibles a partir de este momento). Además, cada fuente de evaluación enviada a GrabFromOnlineSource tiene su propio progreso informado que se cuenta para la fuente de evaluación actual (es decir, eBay tiene su propio progreso, Amazon es propio, etc.).

The EvaluationInfo y 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

Más información:

Una cosa que olvidé mencionar es que el informe de progreso funciona con task.run desde la función evaluateitem pero prefiero modularizar mi código un poco para evitar que una acción ocupe demasiado espacio y es por eso que no he movido el código de GrabFromOnlineSource a evaluateitem.


intenté declarar una variable en la función GrabFromOnlineSource como byref y pasar a este método. después de la modalidad u en GrabFromOnlineSource, puede observar esta variable desde la función principal o cualquier otro lugar.

Perdón, debería verificar eso

Método nr.2

Entonces, ¿por qué no envuelves este proceso en clase, algo así si quieres progresar en 2 tareas, siempre puedes observar este objeto o agregar eventos para el seguimiento del progreso?

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


Perdón por la demora en responder mi propia pregunta, pero aquí va (no soy perfecto para formatear el código, así que un editor o administrador puede arreglarlo):

Este es el código de prueba de clase que utilicé por separado de mis proyectos dll para probar que esto estaba funcionando (también creé un nuevo proyecto para probar mi teoría):

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

Otra cosa que cambió dentro de mi función principal fue mi ciclo de while estaba un poco mal. Necesitaba retrasos entre la aprobación de los informes de progreso o, de lo contrario, no se retractó o se mostró al 100% al final, haciendo inútil mi informe de progreso. Cualquiera puede comentar sobre cómo hacer esto mejor. ¡Es una locura que retrasos perdonados puedan estropear un programa!

Todo lo demás es bastante parecido. Excepto que puse retrasos como los de arriba para que deje de pasar el progreso el tiempo suficiente para que el ojo natural vea el progreso.