Conserver les réglages synchronisés entre les formulaires de demande et le service Windows (ou tout n-tier, vraiment)

StackOverflow https://stackoverflow.com/questions/3167647

Question

J'ai un service Windows qui exécute un certain nombre d'activités périodiques, et je veux changer les paramètres de ce service à partir d'une application Windows Forms. Je ne suis pas sûr, cependant, au sujet de la meilleure façon de vous assurer que le service a les préférences de l'utilisateur le plus mis à jour en elle (la fréquence d'exécution, ce que les dossiers à utiliser pour des choses, tout ce que l'utilisateur peut spécifier). L'utilisateur peut modifier les paramètres en tout temps, à volonté, et je voudrais le savoir de service à ce sujet presque immédiatement. Voici les options que je suis un poids:

  1. La forme et le partage de service utilisent le même objet « Paramètres » d'un troisième projet commun, et le formulaire utilise un WCF « UpdateSettings (newSettings) » appel à laisser le savoir de service qu'il ya eu des changements (ou, le cas échéant, un appel à mettre à jour chaque réglage individuel, bien que cela semble être beaucoup plus différents appels). J'utilise actuellement WCF pour les messages de base, mais l'objet de paramètres peut être énorme, car il y a beaucoup d'autres choses là-dedans
  2. Formulaire et service utilisent un fichier de configuration commun (XML, ou les mêmes paramètres objet de # 1, mais sérialisés sur le disque). Le formulaire écrit simplement une nouvelle copie de l'objet après qu'il a été modifié, et les contrôles de service périodiquement et ramasse si elle est nouvelle, la mise à jour sa copie des paramètres
  3. Identique # 2, mais avec un appel WCF de base qui dit que le service pour aller chercher les paramètres. Pour l'essentiel, une version « à la demande » au lieu de « vote » de # 2.

Je connais le mieux est subjective, mais je suis intéressé par des raisons évidentes pour ou contre ces choix. Depuis que je vais devoir sauver mes paramètres entre runnings de l'application (redémarrages, etc), je vais devoir sérialiser les paramètres sur le disque de toute façon, donc je suis déjà penché vers # 2 ou # 3. Je vais avoir besoin d'un endroit sur le disque où je peux enregistrer les paramètres, mais peut-être le dossier AppData travaillerai bien, mais cela ne permettra aux administrateurs de modifier les paramètres, car ils sont les seuls qui ont la permission d'écrire à cet endroit (où tous les utilisateurs, y compris le compte de service, peut le lire).

Merci pour votre perspicacité!

Était-ce utile?

La solution

J'utilise un peu votre numéro 2.

Mais je ne travaille dans .NET 2 avec ma demande, mais il doit encore appliquer.

J'ai une classe de paramètres que j'utilise dans mes 2 programmes. Dans cette configuration de classe I paramètres FileSystemWatcher objet se penche sur le fichier de paramètres.

Si le fichier de paramètres est mis à jour par l'autre application, mon courant devient un déclencheur d'événement pour indiquer que les paramètres doivent reload.

Vous pouvez également appliquer le même principe dans les paramètres écran de sorte que si le (service) autres mises à jour d'applications quoi que ce soit lors de l'édition des paramètres, qui se reflète dans l'écran.

J'utilise le AppData (ma société / répertoire nom de l'application) pour stocker le fichier.

L'autre chose à garder à l'esprit, est qu'il peut y avoir de blocage sur le fichier alors qu'il est en cours d'écriture de sorte que vous pouvez soit utiliser un nom temporaire enregistrer, supprimer vieux, renommage méthode temporaire ou mettre un peu de verrouillage de protection sur le fichier lorsque la lecture après l'événement se déclenche Filewatcher que des modifications ont été apportées.

J'utilise cette approche dans mon FileSystemWatcher avant de procéder

IPSDependency.FileSystem.WaitForLockOnFile(Me.mFilePath)

le code qui est comme ça. (À la lecture de maintenant, il peut y avoir une meilleure méthode en utilisant mon sommeil ici pour réduire raclée CPU)

Public Shared Function IsLockAvailable(ByVal filename As String, ByVal fnfIsOK As Boolean) As Boolean
    Dim fi As FileInfo
    fi = New FileInfo(filename)
    Return IsLockAvailable(New FileInfo(filename), fnfIsOK)
End Function

Public Shared Function IsLockAvailable(ByVal theFile As FileInfo, ByVal fnfIsOK As Boolean) As Boolean
    Dim fs As FileStream
    Try
        If theFile.Exists Then
            fs = New FileStream(theFile.FullName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
            fs.Close()
            Return True
        Else
            Return fnfIsOK
        End If
    Catch ex As IOException
        'we just let the exception go, because we are only testing the file rather than trying to use it.
        Return False
    End Try
End Function

Public Shared Sub WaitForLockOnFile(ByVal theFilename As String)
    WaitForLockOnFile(New FileInfo(theFilename))
End Sub

Public Shared Sub WaitForLockOnFile(ByVal theFile As FileInfo)
    Dim lockAvailable As Boolean
    If theFile.Exists Then
        While Not lockAvailable
            lockAvailable = IsLockAvailable(theFile, False)
        End While
    End If
End Sub

Autres conseils

En supposant que tout est en cours d'exécution sur la même machine, que diriez-vous:

  1. Définir une structure c # commune qui définit les paramètres. Tous les projets comprennent ce fichier .cs. Définissez cette classe comme struct avec StructLayout séquentielle ou explicite il peut être mis en correspondance directement dans non géré partagé Mémoire. Par exemple:

    [StructLayout (LayoutKind.Sequential)] MySharedSettings struct dangereux {     int SETTING1 public;     int Setting2 public;     chaîne publique Setting3;     // ajouter des champs ici. }

  2. Utilisez nommée mémoire partagée (alias: fichiers mappés en mémoire ). Cela permet à plusieurs processus sur le même ordinateur pour partager des données, sans les frais généraux de Remoting ou WCF . La mémoire partagée est extrêmement rapide et, contrairement à tuyaux, offre un accès aléatoire aux données de mémoire partagée. Le service créer le nom de la mémoire partagée, et les applications de l'interface utilisateur ouvrirait la mémoire partagée. Vous devez utiliser PInvoke pour utiliser les API Windows sous-jacent, mais ce n'est pas une grosse affaire.

  3. Les applications de l'interface utilisateur écrivent les MySharedSettings à la mémoire partagée, alors que le service lit la mémoire partagée.

  4. Utilisez un nom Sémaphore et / ou nom Mutex pour protéger l'accès à la mémoire partagée et signaler la disponibilité de nouveaux paramètres. Le service a un fil d'arrière-plan dédié qui effectuent simplement une WaitOne () sur le sémaphores et le thread d'interface utilisateur signalera lorsque de nouvelles données sont écrites.

En général, les services qui effectuent un (fichiers à savoir synchronisation) « opération de vote » ont assez de temps de retard dans leur intervalle de sondage que vous pouvez tout aussi facilement relire tous les paramètres de chaque boucle, ou même au besoin.

Si votre service est plus le long des lignes d'un back-end SOA, les modifications peuvent affecter les paramètres qui sont généralement utilisés uniquement une fois pendant la durée de vie d'un service. Si ceci est votre type d'application, l'option # 2 vous décrit ci-dessus est le plus fiable. Je ne peux pas dire que je me soucie beaucoup de la mise en œuvre de Paul comme polling un fichier comme cela donnera des résultats peu fiables. Je recommanderais d'utiliser une poignée d'attente nommée globalement pour signaler votre processus de changement. Je suis sûr que vous pouvez trouver un exemple ici sur le SO. Si vous ne voulez pas faire que vous pouvez ensuite interroger le temps de dernière modification du fichier de changement de configuration.

Dans l'ensemble ma préférence est pour la première approche à l'aide du registre pour le stockage. Écrivez tous vos paramètres dans des valeurs discrètes dans une ruche de registre et de les lire à la demande dans votre service. Il est plus rapide que vous pourriez penser et facile à mettre en œuvre à la fois avant et arrière-plan.

Je suis d'accord avec votre direction initiale maigre # 2 et # 3. Je aime particulièrement le # 3 car je ne suis pas fan de vote, mais en fin de compte, je pense que la décision entre n ° 2 ou n ° 3 sera tirée par les exigences de votre service.

En ce qui concerne le stockage des paramètres utilisateur je recommande l'exploration de stockage isolé ( http: //msdn.microsoft.com/en-us/library/3ak841sy.aspx ). Il offre un excellent mécanisme pour un accès sécurisé, cohérent et fiable pour les fichiers utilisateur. Vous n'aurez pas à vous soucier de l'autorisation de l'utilisateur ayant moins que l'administrateur a complètement désactivé le stockage isolé. De plus, si vous activez l'itinérance, les utilisateurs peuvent même prendre leurs paramètres avec eux s'ils utilisent différents systèmes sur le même domaine, assez lisse hein?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top