Actualmente estoy escribiendo una aplicación que controlará el posicionamiento de un dispositivo de medición. Debido al hardware involucrado, necesito sondear constantemente el valor de la posición actual mientras estoy usando el motor eléctrico. Intento crear la clase responsable de esto para que realice el sondeo en un hilo de fondo y genere un evento cuando se alcanza la posición deseada. La idea es que el sondeo no bloqueará el resto de la aplicación o la GUI. Quería usar la nueva clase Threading.Task.Task para manejar todas las conexiones de fondo de subprocesos para mí..Net ¿por qué Threading.Task.Task aún bloquea mi UI?
Aún no tengo el hardware, pero tengo un compilador de prueba para simular este comportamiento. Pero cuando ejecuto la aplicación de esta manera, la GUI aún bloquea. Vea un ejemplo simplificado del código a continuación (no completo y sin usar una clase separada para el control del dispositivo). El código tiene una secuencia de pasos de medición, la aplicación debe posicionarse y luego medir para cada paso.
public partial class MeasurementForm: Form
{
private MeasurementStepsGenerator msg = new MeasurementsStepGenerator();
private IEnumerator<MeasurementStep> steps;
// actually through events from device control class
private void MeasurementStarted()
{
// update GUI
}
// actually through events from device control class
private void MeasurementFinished()
{
// store measurement data
// update GUI
BeginNextMeasurementStep();
}
private void MeasurementForm_Shown(object sender, EventArgs e)
{
steps = msg.GenerateSteps().GetEnumerator();
BeginNextMeasurementStep();
}
...
...
private void BeginNextMeasurementStep()
{
steps.MoveNext();
if (steps.Current != null)
{
MeasurementStarted();
MeasureAtPosition(steps.Current.Position);
}
else
{
// finished, update GUI
}
}
// stub method for device control (actually in seperate class)
public void MeasureAtPosition(decimal position)
{
// simulate polling
var context = TaskScheduler.FromCurrentSynchronizationContext();
Task task = Task.Factory.StartNew(() =>
{
Thread.Sleep(sleepTime);
}, TaskCreationOptions.LongRunning)
.ContinueWith(_ =>
{
MeasurementFinished();
}, context);
}
}
Yo esperaría que la tarea se ejecute el comando Thread.Sleep en un subproceso en segundo plano por lo que el control vuelve al hilo principal de inmediato y la interfaz gráfica de usuario no se bloquean. Pero la GUI aún se bloquea. Es como si la tarea se ejecutara en el hilo principal. ¿Alguna idea sobre lo que estoy haciendo mal aquí?
Gracias
He probado esto con algún algoritmo pesado en lugar de Thread.Sleep y todo funciona bien entonces. ¿Thread.Sleep siempre funciona en el hilo principal? Esperaría que funcione en el hilo actual. – Stefan
Quiero decir que esperaría que bloqueara el hilo de la tarea, no el hilo de la interfaz de usuario. – Stefan
Descubrí que la ejecución de tareas en serie con ContinueWith() bloquea la UI, ya sea que use un algoritmo pesado o Thread.Sleep(). No hace esto para el algoritmo pesado cuando ejecuta tareas paralelas, pero no puedo hacer eso, mis tareas tienen que ejecutarse en orden. – Stefan