No soy fan de los diálogos de progreso. ¿Por qué? Creo que la mayoría mienten. 3 segundos para llegar al 98% y luego 10 minutos para el último 2%.
¿Qué? Podemos hacerlo mejor. Usemos el diálogo de progreso de Data Management de OneStream para realmente informar al usuario y decir la verdad sobre la tarea en ejecución.
Ya que estamos, también demos al usuario la posibilidad de cancelar una tarea en ejecución y hacer que esa tarea realmente se detenga.
Si ha creado cualquier tipo de proceso de Data Management de larga duración dentro de OneStream, del tipo que recorre meses o llama a sistemas externos, entonces seguramente ya pensó que sería útil proporcionar retroalimentación útil mientras se ejecuta.
Ahí es donde entra BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled. Le permite enviar mensajes de estado al diálogo de Data Management y, igual de importante, comprobar si el usuario decidió cancelar el proceso.
El patrón básico es simple: llame a este método de forma periódica dentro de su código, pase un mensaje que describa lo que está haciendo y use el valor booleano true o false para decidir si debe salir.
No disfruto escribir nombres de funciones de más de 60 caracteres, enterrados varios objetos dentro de una librería.
Y BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled es justo uno de esos casos feos. Solo necesita una API. Así que escribamos una. En este caso, es un simple método wrapper de una línea llamado UpdateDMDialog(message As String).
La función devuelve el mismo booleano que nuestra función de librería de más de 60 caracteres, indicando si el usuario hizo clic en cancelar. Entonces, si devuelve true, sé que el usuario canceló el proceso y también puedo salir de mi código. Eso les da a los usuarios una forma de detener el proceso sin matar el servidor ni esperar un timeout.
Vea el código de abajo para un ejemplo simulado y funcional de cómo usar BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled.
El verdadero valor aquí está en los mensajes que envía. Piense menos en “30% completado” y más en “Obteniendo registros de mayo…” o “Esperando trabajo 12734 de NetSuite…”. Cualquier cosa que muestre qué está ocurriendo y en qué punto del proceso se encuentra le da confianza al usuario, o al menos una idea de si debería ir por un café o cancelar. Incluso puede incluir recuentos de registros, IDs de tareas o latencia de API si quiere ponerse elegante.
Uso este patrón en integraciones de datos, importaciones de archivos y prácticamente en cualquier lugar donde las cosas puedan tardar o fallar a mitad del proceso. Es liviano, le da control al usuario y es mucho mejor que dejarlos mirando un diálogo giratorio que engaña sobre el progreso real. Agregue algunas llamadas a UpdateDMDialog dentro de su loop y listo, usuario feliz e informado.
C#
public class DataImporter
{
private readonly object si;
private readonly object _args;
private readonly string _dataType;
private decimal _progress;
public DataImporter(object sessionInfo, object args, string dataType)
{
si = sessionInfo;
_args = args;
_dataType = dataType;
_progress = 0m;
}
private bool UpdateDMDialog(string message)
{
return BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled(si, _args, message, _progress);
}
public async Task GetData(string yearInput)
{
var response = new List();
long totalRecords = 0;
UpdateDMDialog($"Starting {_dataType} import for year {yearInput}");
for (int month = 1; month r.ItemArray), Formatting.Indented);
UpdateDMDialog($"All months complete. Total records: {totalRecords}");
BRApi.ErrorLog.LogMessage(si, $"Preview:
{preview}");
return table;
}
private Task Mock_DataRequestStart(string month)
=> Task.FromResult(Guid.NewGuid().ToString());
private Task Mock_DataRequestStatus(string taskId)
=> Task.Delay(200);
private Task Mock_DataRequestComplete(string month, string taskId)
=> Task.FromResult(new DataResult
{
Data = new List { "header", $"data for {month}" },
RecordCount = 1
});
private DataTable Mock_ToDataTable(List rows)
{
var table = new DataTable();
table.Columns.Add("Content", typeof(string));
foreach (var row in rows)
table.Rows.Add(row);
return table;
}
private class DataResult
{
public List Data { get; set; }
public long RecordCount { get; set; }
}
}
VB.NET
Public Class DataImporter
Private ReadOnly si As Object
Private ReadOnly _args As Object
Private ReadOnly _dataType As String
Private _progress As Decimal
Public Sub New(sessionInfo As Object, args As Object, dataType As String)
Me.si = sessionInfo
Me._args = args
Me._dataType = dataType
Me._progress = 0D
End Sub
Private Function UpdateDMDialog(message As String) As Boolean
Return BRApi.TaskActivity.UpdateRunningTaskActivityAndCheckIfCanceled(si, _args, message, _progress)
End Function
Public Async Function GetData(yearInput As String) As Task(Of DataTable)
Dim response As New List(Of String)()
Dim totalRecords As Long = 0
UpdateDMDialog($"Starting {_dataType} import for year {yearInput}")
For month As Integer = 1 To 12
Dim monthStr As String = $"{yearInput}-{month:D2}"
UpdateDMDialog($"Starting {monthStr}...")
Dim taskId As String = Await Mock_DataRequestStart(monthStr)
Await Mock_DataRequestStatus(taskId)
Dim result As DataResult = Await Mock_DataRequestComplete(monthStr, taskId)
_progress = month * 8.33D
UpdateDMDialog($"Finished {monthStr} - {result.RecordCount} records")
If result.Data IsNot Nothing Then
If response.Count = 0 Then
response.AddRange(result.Data)
Else
response.AddRange(result.Data.Skip(1))
End If
totalRecords += result.RecordCount
End If
If UpdateDMDialog($"Imported {monthStr}") Then
Return New DataTable()
End If
Next
Dim table As DataTable = Mock_ToDataTable(response)
Dim preview As String = JsonConvert.SerializeObject(
table.AsEnumerable().Take(5).Select(Function(r) r.ItemArray),
Formatting.Indented
)
UpdateDMDialog($"All months complete. Total records: {totalRecords}")
BRApi.ErrorLog.LogMessage(si, $"Preview:{vbLf}{preview}")
Return table
End Function
Private Function Mock_DataRequestStart(month As String) As Task(Of String)
Return Task.FromResult(Guid.NewGuid().ToString())
End Function
Private Function Mock_DataRequestStatus(taskId As String) As Task
Return Task.Delay(200)
End Function
Private Function Mock_DataRequestComplete(month As String, taskId As String) As Task(Of DataResult)
Dim result As New DataResult With {
.Data = New List(Of String) From {"header", $"data for {month}"},
.RecordCount = 1
}
Return Task.FromResult(result)
End Function
Private Function Mock_ToDataTable(rows As List(Of String)) As DataTable
Dim table As New DataTable()
table.Columns.Add("Content", GetType(String))
For Each row As String In rows
table.Rows.Add(row)
Next
Return table
End Function
Private Class DataResult
Public Property Data As List(Of String)
Public Property RecordCount As Long
End Class
End Class
Contacto
MindStream Analytics
¿Quiere saber más sobre OneStream Software? Complete el siguiente formulario y nos pondremos en contacto con usted en breve.
