2010-08-29 9 views
2

J'ai un arrière-plan qui vérifie l'état de quatre services sur un serveur distant. Ceci est configuré sur une minuterie (5 secondes) comme ci-dessous. Pour une raison quelconque, il est suspendu le fil de l'interface utilisateur provoquant le verrouillage de l'application pour une seconde chaque tick, je ne peux pas comprendre pourquoi ?!Fil d'arrière-plan entraînant le blocage de l'interface utilisateur

Private Sub ServiceTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ServiceTimer.Tick 

    _ServiceBGWorker = New System.ComponentModel.BackgroundWorker() 
    _ServiceBGWorker.WorkerSupportsCancellation = False 
    _ServiceBGWorker.WorkerReportsProgress = False 
    AddHandler _ServiceBGWorker.DoWork, New DoWorkEventHandler(AddressOf Me.CheckService) 

    _ServiceBGWorker.RunWorkerAsync() 
    While _ServiceBGWorker.IsBusy 
     Application.DoEvents() 
    End While 
End Sub 

Private Sub CheckService(ByVal sender As Object, ByVal e As DoWorkEventArgs) 

    If CheckService("Service 3.5") = ServiceControllerStatus.Stopped Then 
     PBServiceStatus35.Image = ImgStopIcon 
    ElseIf CheckService("Service 3.5") = ServiceControllerStatus.Running Then 

     PBServiceStatus35.Image = ImgGoIcon 
    Else 
     PBServiceStatus35.Image = ImgHelpIcon 
    End If 

    If CheckService("Service 3.6") = ServiceControllerStatus.Stopped Then 

     PBServiceStatus36.Image = ImgStopIcon 
    ElseIf CheckService("Service 3.6") = ServiceControllerStatus.Running Then 

     PBServiceStatus36.Image = ImgGoIcon 
    Else 
     PBServiceStatus36.Image = ImgHelpIcon 
    End If 

    If CheckService("Service 3.7") = ServiceControllerStatus.Stopped Then 
     PBServiceStatus37.Image = ImgStopIcon 
    ElseIf CheckService("Service 3.7") = ServiceControllerStatus.Running Then 
     PBServiceStatus37.Image = ImgGoIcon 
    Else 
     PBServiceStatus37.Image = ImgHelpIcon 
    End If 

    If CheckService("Service 4.0") = ServiceControllerStatus.Stopped Then 
     PBServiceStatus40.Image = ImgStopIcon 
    ElseIf CheckService("Service 4.0") = ServiceControllerStatus.Running Then 
     PBServiceStatus40.Image = ImgGoIcon 
    Else 
     PBServiceStatus40.Image = ImgHelpIcon 
    End If 
End Sub 


Private Function CheckService(ByVal ServiceName As String) 
    Dim myController = New ServiceController(ServiceName) 
    myController.MachineName = SQLServerName 
    myController.Refresh() 
    Return myController.Status 
End Function 
+0

Pourquoi créez-vous un nouveau BackgroundWorker pour chaque tick de service? Ne serait-il pas mieux de réutiliser un BackgroundWorker existant en appelant DoWork' à plusieurs reprises? –

+0

@Robert: difficile si un travail bgw peut prendre plus de 5 secondes. Un bgw n'est pas rentrant. –

+0

Mieux vaut utiliser ThreadPool.QueueUserWorkItem (http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx) - vous n'aurez pas la surcharge de la création de threads si vous faites cela. –

Répondre

1

Cette boucle while est complètement inutile:

While _ServiceBGWorker.IsBusy 
    Application.DoEvents() 
End While 

Je ne vois pas comment cela pourrait causer votre problème direct ici cependant, mais vous pourriez essayer sans. Sur une note connexe, il serait judicieux d'ajouter un gestionnaire Terminé et de vérifier l'état e.Error. Peut-être que quelque chose jette des exceptions. Avec votre code actuel, vous ne saurez jamais.

+0

Je ne serais pas surpris si ces boucles causent le problème, tho '. –

+0

Ahh, enlever la boucle a résolu le problème - je pensais que c'était nécessaire pour mettre à jour les images. – madlan

+0

@madian: Mais corrigez aussi votre gestion des exceptions. Faites-en une habitude. –

2

Il ne serait pas dommage de revoir la documentation MSDN Background Worker Class. Une note qui lit

Vous devez veiller à ne pas manipuler les objets de l'interface utilisateur dans votre gestionnaire d'événements DoWork. Au lieu de cela, communiquez avec l'interface utilisateur via les événements ProgressChanged et RunWorkerCompleted.

Ainsi, au lieu de manipuler votre zone d'image dans votre gestionnaire DoWork, utilisez les gestionnaires mentionnés ci-dessus. J'ai écrit deux formulaires simples et en charge un à partir d'un gestionnaire DoWork et le formulaire et l'interface utilisateur indéfiniment suspendue lorsque le formulaire est chargé à partir de DoWork, mais répond correctement des autres.

+0

Vous n'avez pas besoin d'ajouter une signature à vos messages. [C'est déjà fait pour vous] (http://stackoverflow.com/faq#signatures). – Joshua