Attualmente sto scrivendo un'applicazione che controllerà il posizionamento di un dispositivo di misurazione. A causa dell'hardware coinvolto ho bisogno di eseguire il polling per il valore di posizione corrente costantemente durante l'esecuzione del motore elettrico. Sto cercando di creare la classe responsabile di questo in modo che esegua il polling su un thread in background e genererà un evento quando viene raggiunta la posizione desiderata. L'idea è che il sondaggio non bloccherà il resto dell'applicazione o la GUI. Volevo utilizzare la nuova classe Threading.Task.Task per gestire tutti gli impianti idraulici di thread in background per me..Net perché Threading.Task.Task blocca ancora la mia UI?
Non ho ancora l'hardware, ma ho creato uno stub di prova per simulare questo comportamento. Ma quando eseguo l'applicazione in questo modo, la GUI continua a bloccarsi. Vedere un esempio semplificato del codice seguente (non completo e non utilizzando una classe separata per il controllo del dispositivo). Il codice ha una sequenza di passaggi di misurazione, l'applicazione deve posizionare e quindi misurare per ogni passaggio.
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);
}
}
mi si aspetterebbe il compito di eseguire il comando Thread.Sleep su un thread in background in modo da controllo ritorna al thread principale immediatamente e l'interfaccia grafica non si bloccano. Ma la GUI viene ancora bloccata. È come l'attività viene eseguita sul thread principale. Qualche idea su cosa sto facendo male qui?
Grazie
Ho provato questo con un algoritmo pesante invece di Thread.Sleep e tutto funziona correttamente. Thread.Sleep funziona sempre sul thread principale? Mi aspetterei che funzioni nel thread corrente. – Stefan
Voglio dire che mi aspetterei che blocchi il thread dell'attività, non il thread dell'interfaccia utente. – Stefan
Ho scoperto che l'esecuzione di Task in serie con ContinueWith() blocca l'interfaccia utente, indipendentemente dal fatto che io usi un algoritmo pesante o Thread.Sleep(). Non lo fa per l'algoritmo pesante quando esegui attività parallele, ma non posso farlo, i miei compiti devono essere eseguiti in ordine. – Stefan