2009-02-07 8 views
8

Sto provando ad utilizzare l'oggetto .NET BackgroundWorker in un'applicazione sto sviluppando..NET BackgroundWorker oggetto

Tutto il materiale su Internet dice che questo oggetto viene eseguito nello "sfondo" ma da nessuna parte ho potuto verificare che questo thread in background funzioni effettivamente in modalità "bassa priorità". Questa domanda si pone perché in Windows (presumo) attività in background può essere eseguito in un 'normale' o 'al di sotto normale' o in modalità di priorità 'basso'.

Nella mia applicazione, ho cercato di impostare la priorità di me stesso all'interno della funzione DoWork chiamando ...

Thread.CurrentThread.Priority=ThreadPriority.Lowest 

...

ma questo sembra non avere alcun effetto. Il Backgroundworker ignora questa chiamata?

Vorrei spiegare alcune di più:

La mia applicazione è un client Internet che raccoglie i dati in tempo reale su temperatura, umidità ecc da una camera e upload ad una pagina web (non è un servizio web) utilizzando

system.net.webclient.UploadValuesAsync(...) chiama

ho scritto l'applicazione in modo tale che la GUI del client raccoglie i dati dalla camera, loro il tempo-francobolli e poi le mette in coda per l'upload in questo modo

...

Synclock objlock 
    debug.print("Queueing reading...") 
    dataQ.Enque(reading) 
End Synclock 
... 

Ritiri dalla coda funzione DoWork del BackgroundWorker e poi arrivi in ​​questo modo ...

..............

Do 
     if dataQ.count() <> 0 then 
      Synclock objlock 
       reading = dataQ.DeQue() 
      End Synclock 
      Dim client As New System.Net.WebClient 
      ...put the reading in NameValueCollection and upload to server page 
      req = new NameValueCollection 
      ... 
      ... 
      client.UploadValuesAsync(uri, "POST", req) 
     endif 
     thread.sleep(1) 'without this line the CPU usage goes upto 100% and seems to slow other tasks! 
    Loop 

..... ...........

Quando eseguo il programma trovo che ogni volta che l'UploadValuesAsync è chiamata la stampa fuori arresta la finestra di debug. Ho anche aggiunto delle istruzioni di debug per vedere quante letture sono in coda in qualsiasi momento. E questo compito è veramente eseguito in una bassa priorità, mi aspettavo di vedere l'aumento conteggio di coda rapidamente dati sono acquisiti e poi diminuire solo quando in primo piano è inattivo ei dati non viene acquisito. Ma questo non è il caso. Non appena viene aggiunta una lettura alla coda, viene rimossa dalla coda e caricata. Quindi il conteggio delle code è sempre 1 o 0!

C'è qualcosa che non va nel mio approccio? Non dovrei usare affatto l'oggetto background-worker?

BTW, questo è in un laptop dual-core con Windows XP.

risposta

13

Giusto per aggiungere a quello che Jon e Marc hanno già detto: le discussioni

sfondo non hanno priorità inferiore. La differenza tra i thread in primo piano e in background è che CLR interromperà il processo una volta che non sono in esecuzione altri thread in primo piano. I thread del pool di thread sono thread in background.

In realtà è possibile impostare la priorità di un thread pool di thread, ma non avendo alcun controllo su quale thread thread thread eseguirà effettivamente l'attività, non è consigliabile farlo. Se hai bisogno di thread con una priorità specifica dovresti crearli usando il tipo Thread e impostare la priorità sull'istanza come desiderato.

+1

Come mai non posso etichettare TUTTE le risposte come utili? Ognuno di loro ha alcuni suggerimenti utili ...! –

+2

Puoi selezionare solo una risposta, ma puoi votare tutte le risposte che ritieni utili. –

3

Non ha la priorità bassa: lo sfondo indica a: non il thread dell'interfaccia utente e b: non mantiene attivo un processo. In realtà, probabilmente si riferisce a ThreadPool discussioni.

Se si desidera un filo priorità specifica, quindi utilizzare il proprio Thread oggetto - ma io non lo consiglio anche questo di solito ...

Inoltre - "sfondo" non vuol dire "quando inattivo". Anche su una macchina single core, probabilmente vedrai che entrambi i thread ottengono tanto rnutime (se lo vogliono). Ancora di più su multi-core.

+0

Il problema è quando il thread in background sta chiamando l'UploadAsync, sembra essere il blocco/rallentare il thread dell'interfaccia utente. Posso dire questo perché le dichiarazioni di debug si fermano quando si verifica il caricamento. Come posso evitare questo? –

+0

Quanti core hai? Il lavoro deve accadere da qualche parte ... –

+0

È un laptop dual-core con Win XP. –

7

Sì, c'è qualcosa di sbagliato nel tuo approccio: sei praticamente in loop quando la coda è vuota. Qualunque sia la priorità del thread, è una cattiva idea.

Non c'è niente di sbagliato nell'usare un lavoratore in background per questo, ma l'enqueuing/dequeuing dovrebbe davvero usare solo una coda producer/consumer che blocca quando si tenta di dequeue quando non c'è nulla di pronto.

Ho un'implementazione di esempio di una coda produttore/consumatore in my threading tutorial - vedere circa a metà della pagina collegata. A proposito, vorresti un modo per dire al processo di smantellamento che è finito. (Ad esempio, accodando un riferimento null o un altro valore speciale.) Quel codice è stato scritto pre-generico, ma dovrebbe essere facile da aggiornare.

+0

Nel tuo esempio, ci si aspetta 10 articoli nella coda e il thread consumatore termina quando si deseleziona 10 elementi. Nel mio caso, gli articoli vengono aggiunti alla coda per tutto il ciclo di vita dell'applicazione (circa 10 voci al secondo), quindi oWork non dovrebbe mai terminare. Quindi che altro da fare, ma ciclo stretto? –

+0

@Soundar: l'unica differenza è la condizione di terminazione. Come ho suggerito nella risposta, è possibile utilizzare un valore speciale (ad esempio null) per indicare la terminazione o semplicemente non terminare mai. L'importante è bloccare (invece di fare il ciclo) quando non ci sono voci. –

+0

Grazie. Leggendo ulteriormente i tuoi tutorial, ora so cosa ho sbagliato. Dovrei usare Monitor.sleep invece di thread.sleep (mi chiedevo perché ne avessi bisogno comunque). E monitor.wait sembra funzionare all'interno della funzione DoWork. –