保持表单应用程序和Windows服务(或任何n层,真正)之间的设置同步

Sql*_*yan 5 .net wcf serialization multi-tier application-settings

我有一个Windows服务,执行一些定期活动,我想从Windows窗体应用程序更改此服务的设置.但是,我不确定是否有最好的方法来确保服务中包含最新的用户首选项(运行频率,用于事物的文件夹,用户可以指定的任何其他内容).用户可以随时随地更改设置,我希望服务几乎立即就知道了.以下是我正在权衡的选项:

  1. 表单和服务共享使用来自第三个共享项目的相同"设置"对象,并且表单使用WCF"UpdateSettings(newSettings)"调用让服务知道已发生更改(或者,可选地,调用更新每个单独的设置,虽然这似乎很多不同的电话).我目前使用WCF作为基本消息,但设置对象可能很大,因为那里有很多其他的东西
  2. 表单和服务使用公共配置文件(XML,或#1中的相同设置对象,但序列化为磁盘).表单只是在更改后写入对象的新副本,并且服务会经常检查并在新的时候进行检查,更新其设置副本
  3. 与#2相同,但有一个基本的WCF调用,告诉服务去获取设置.基本上,是"按需"而不是"轮询"版本的#2.

我知道最好是主观的,但我对这些选择的任何明显的赞成或反对的原因感兴趣.因为我必须在应用程序的运行之间保存我的设置(重新启动等),所以我必须将设置序列化到磁盘,所以我已经倾向于#2或#3.我需要在磁盘上放置一个可以保存设置的地方,但也许AppData文件夹可以正常工作,但这只会让管理员更改设置,因为他们是唯一有权写入此位置的人(每个用户,包括服务帐户,都可以阅读它).

感谢您的见解!

Pau*_*rry 3

我有点用你的2号。

但我只在 .NET 2 中使用我的应用程序,但它应该仍然适用。

我有一个在两个程序中使用的设置类。在这个设置类中,我设置了一个FileSystemWatcher 对象来查看设置文件。

如果其他应用程序更新了设置文件,我的当前应用程序会收到一个事件触发器来指示需要重新加载设置。

您还可以在设置屏幕中应用相同的原则,以便如果(服务)其他应用程序在设置编辑期间更新任何内容,则会反映在您的屏幕中。

我使用AppData(我的公司/应用程序名称目录)来存储文件。

另一件要记住的事情是,在写入文件时可能会锁定文件,因此您可以使用临时名称保存、删除旧的、重命名临时方法,或者在写入后读取文件时对文件进行一些保护性锁定。 filewatcher 事件触发已进行更改。

在继续之前,我在FileSystemWatcher中使用此方法

IPSDependency.FileSystem.WaitForLockOnFile(Me.mFilePath)
Run Code Online (Sandbox Code Playgroud)

其代码是这样的。(现在阅读本文后,可能有更好的方法,我在这里使用一些睡眠来减少 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
Run Code Online (Sandbox Code Playgroud)