2009-02-07 3 views
8

J'essaie d'utiliser l'objet .NET Backgroundworker dans une application que je développe.Priorité de thread de l'objet .work arrière-plan

Tout le matériel sur Internet dit que cet objet s'exécute dans le "background" mais nulle part j'ai pu confirmer que ce thread d'arrière-plan s'exécute en effet dans un mode "basse priorité". Cette question se pose parce que dans Windows (je suppose) une tâche de fond peut fonctionner dans un mode de priorité «normal» ou «en dessous de la normale» ou «faible».

Dans ma demande, j'ai essayé de définir la priorité moi-même dans la fonction DoWork en appelant ...

Thread.CurrentThread.Priority=ThreadPriority.Lowest 

...

mais cela semble avoir aucun effet. L'arrière-plan ignore-t-il cet appel?

Je voudrais expliquer un peu plus:

Ma demande est un client Internet qui recueille des données en temps réel sur la température, l'humidité, etc. d'une chambre et télécharge vers une page Web (pas un service Web) en utilisant

system.net.webclient.UploadValuesAsync(...) appelle

J'ai écrit l'application de telle sorte que l'interface graphique du client recueille les données de la chambre, horodatées et ensuite les files d'attente pour le téléchargement comme si

...

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

La fonction DoWork de BackgroundWorker de dequeues puis ajouts comme si ...

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

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 

..... ...

Lorsque j'exécute le programme, je constate que chaque fois que UploadValuesAsync est appelé, la fenêtre de débogage s'arrête. J'avais également ajouté des instructions de débogage pour voir le nombre de lectures dans la file d'attente à tout moment. Si cette tâche est réellement exécutée avec une priorité faible, je m'attendais à voir le nombre de files d'attente augmenter rapidement à mesure que les données sont acquises, puis diminuer seulement lorsque le premier plan est inactif et que les données ne sont pas acquises. Mais ce n'est pas le cas. Dès qu'une lecture est ajoutée à la file d'attente, elle est supprimée et téléchargée. Donc, le nombre de files d'attente est toujours 1 ou 0!

Y a-t-il quelque chose qui ne va pas dans ma démarche? Est-ce que je ne devrais pas utiliser l'objet background-worker? Par ailleurs, il s'agit d'un ordinateur portable dual-core fonctionnant sous Windows Xp.

Répondre

13

Juste pour ajouter à ce que Jon et Marc ont déjà dit:

fils d'arrière-plan n'ont pas moins prioritaire. La différence entre les threads de premier plan et d'arrière-plan est que le CLR arrêtera le processus dès qu'il n'y aura plus de threads de premier plan. Les threads de pool de threads sont des threads d'arrière-plan.

Vous pouvez en fait définir la priorité d'un thread de pool de threads, mais comme vous n'avez aucun contrôle sur le thread de pool de threads qui exécutera réellement votre tâche, il est déconseillé de le faire. Si vous avez besoin de threads d'une priorité spécifique, vous devez les créer en utilisant le type Thread et définir la priorité sur l'instance comme vous le souhaitez.

+1

Comment se fait-il que je ne puisse pas marquer TOUTES les réponses comme utiles? Chacun d'eux a quelques suggestions utiles ...! –

+2

Vous ne pouvez sélectionner qu'une seule réponse, mais vous pouvez voter toutes les réponses que vous trouvez utiles. –

3

Il ne prétend pas être une priorité basse - l'arrière-plan signifie: pas le fil d'interface utilisateur, et b: il ne gardera pas un processus actif. En réalité, cela concerne probablement les threads ThreadPool.

Si vous voulez un fil de priorité spécifique, puis utilisez votre propre Thread objet - mais je ne recommanderais pas même cela normalement ...

De plus - « arrière-plan » ne signifie pas « au repos ». Même sur une seule machine principale, vous verrez probablement que les deux threads obtiennent autant de rnutime (s'ils le veulent). Encore plus sur multi-core.

+0

Le problème est lorsque le fil de fond appelle le UploadAsync, il semble bloquer/ralentir le thread d'interface utilisateur. Je peux le dire parce que les instructions de débogage s'arrêtent lorsque le téléchargement se produit. Comment puis-je éviter ça? –

+0

Combien de noyaux avez-vous? Le travail doit se produire quelque part ... –

+0

Il s'agit d'un ordinateur portable dual core avec Win XP. –

7

Oui, quelque chose ne va pas dans votre approche - vous êtes fondamentalement en boucle lorsque la file d'attente est vide. Quelles que soient les priorités des threads, c'est une mauvaise idée. Il n'y a rien de mal à utiliser un background worker pour cela, mais la mise en file d'attente/dequeuing doit simplement utiliser une file d'attente producteur/consommateur qui bloque lorsque vous essayez de déquiler quand il n'y a rien de prêt.

J'ai un exemple de mise en œuvre d'une file d'attente producteur/consommateur in my threading tutorial - voir à peu près à mi-chemin de la page liée. Vous aurez besoin d'un moyen de dire au processus dequeuing qu'il est terminé, soit dit en passant. (Par exemple, mettre en file d'attente une référence nulle ou une autre valeur spéciale.) Ce code a été écrit en pré-génériques, mais il devrait être facile à mettre à jour.

+0

Dans votre exemple, vous attendez 10 éléments dans la file d'attente et le thread consommateur se termine lorsqu'il supprime 10 éléments. Dans mon cas, les éléments sont ajoutés à la file tout au long du cycle de vie de l'application (environ 10 éléments par seconde), de sorte que oWork ne devrait jamais se terminer. Alors quoi d'autre à faire, mais une boucle serrée? –

+0

@Soundar: La seule différence est la condition de terminaison. Comme je l'ai suggéré dans la réponse, vous pouvez utiliser une valeur spéciale (par exemple, null) pour indiquer la fin - ou simplement ne jamais terminer. L'important est de bloquer (au lieu de boucler) quand il n'y a pas d'entrées. –

+0

Merci. Sur la lecture de vos tutoriels, je sais maintenant ce que j'ai fait de mal. Je devrais utiliser Monitor.sleep au lieu de thread.sleep (je me demandais pourquoi j'avais besoin de ça de toute façon). Et monitor.wait semble fonctionner dans la fonction DoWork. –

Questions connexes