Hai diverse possibilità per fare quello che vuoi, ad esempio:
se vuoi mandare dati ogni "tot" secondi puoi usare un Timer, ti consiglio della libreria
codice:
using System.Timers;
lo inizializzi quando la finestra è pronta
codice:
private System.Timers.Timer m_Timer;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
m_Timer = new System.Timers.Timer();
m_Timer.Elapsed += Timer_Elapsed;
m_Timer.Interval = 4000; // in millisecondi
}
e lo fai partire quando lo ritieni più opportuno
la funzione associata all'evento Elapsed definita da te viene richiamata ogni "interval" tempo
questa funzione è in parallelo al thread principale dell'applicazione e quindi dell'UI pertanto è non bloccante.
codice:
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
// scrivi il codice da svolgere ogni "interval" tempo.
}
Ricordati anche di fermare il timer quando termini le operazioni.
codice:
protected override void OnClosing(CancelEventArgs e)
{
m_Timer.Stop();
m_Timer.Dispose();
base.OnClosing(e);
}
chiaramente utilizzando un thread devi stare attento a non far collidere le informazioni tra di loro, ad esempio se la tua funzione impiegasse di più di 4 secondi a svolgersi, rischi di avere conflitti di operazioni e quindi variabili non coerenti, devi decidere te come gestire il fatto.
per il fatto della barra di progressione, se la marchi indeterminata, cioè rappresentata dalla linea che scorre all'infinito, ti basta semplicemente all'inizio della funzione Timer_Elapsed renderla visibile, ed al termine la nasconderla nuovamente, anche qui devi stare attento alla manipolazione di controlli di interfaccia che non appartengo al Timer ma bensì al Dispacher dell'applicativo.
oppure come hai optato
il BackgroundWorker è un altro tipo di thread ad eventi
codice:
private BackgroundWorker m_Worker;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
m_Worker = new BackgroundWorker();
m_Worker.DoWork += Worker_DoWork; // definisci cosa fare in asincrono
m_Worker.ProgressChanged += Worker_ProgressChanged; // definisci cosa fare al richiamo di m_Worker.ReportProgress(int)
m_Worker.RunWorkerCompleted += Worker_RunWorkerCompleted; // richiamato al termine della vita del thread
m_Worker.WorkerSupportsCancellation = true; // supporta la cancellazione
m_Worker.WorkerReportsProgress = true; // supporta la progressione
}
se la questione che avevi citato prima del fatto che il Worker.ReportProgress permette solo un dato di tipo int è perchè concettualmente
il valore di progressione della barra è un numero intero, nulla ti impedisce che quando è arrivato il valore lo trasformi in stringa e ci applichi ad esempio la percentuale.
Questo implica però che la barra sia realmente in progressione e non indeterminata, nel secondo caso non ti serve gestire questo evento.
Potresti fare un BackgroundWorker con un DoWork infinito (while(true)) all'interno (più simile a Java) e metterlo in sleep ogni "tot" secondi con
codice:
Thread.Sleep(4000) // in millisecondi
anche se per l'SO implica lavoro aggiuntivo.
inoltre, in questo caso, devi anche abilitarne la cancellazione che gestirai tramite
codice:
if ((Worker.CancellationPending == true))
{
e.Cancel = true;
break; // uscire dall'eventuale (while(true))
}
con il comando
codice:
m_Worker.CancelAsync();
un altra alternativa, chiaramente se il tuo progetto si basa sul Framework 4.5 o superiore e l'utilizzo di async e await con la gestione Task, "thread", consigliati rispetto a BackgroundWorker.
se vuoi approfondire, cmq richiede un po' di conoscenza nel linguaggio c#:
https://msdn.microsoft.com/it-it/library/hh191443.aspx
codice:
protected async void StartLoop()
{
await Task.Run(() => DoWork());
}
protected void DoWork()
{
while (true)
{
// scrivi il codice da svolgere ogni ciclo.
}
}
chiaramente anche in questo caso devi darli tu i tempo di esecuzione, devi proteggere l'accesso ai componenti UI, anche se puoi evitare posizionando bene il codice, comunque il vantaggio concreto è che non devi preoccuparti dell'accesso alle variabili in conflitto e non devi preoccuparti per l'accumulo di eventuali altri thread essendo gestiti da un threadpool.
in questo caso per le attese puoi usare
codice:
await Task.Delay(1000);
Queste presentate sono alcune possibilità, puoi trovarne altre, tutto dipende da quale è il compito generale dell'applicativo, ti conviene provarle tutte, verificare quale rispecchia di più le tue esigenze e di conseguenza utilizzarla nel modo più appropriato.