我有一个执行许多定期活动的 Windows 服务,并且我想从 Windows 窗体应用程序更改此服务的设置。不过,我不确定确保服务具有最新的用户首选项的最佳方法(运行频率、使用哪些文件夹、用户可以指定的其他内容)。用户可以随时随意更改设置,我希望服务几乎立即知道这一点。以下是我正在权衡的选项:

  1. 表单和服务共享使用来自第三个共享项目的相同“Settings”对象,并且表单使用 WCF“UpdateSettings(newSettings)”调用来让服务知道已发生更改(或者,可选地,调用更新每个单独的设置,尽管这在不同的调用中似乎很多)。我目前使用 WCF 来处理基本消息,但设置对象可能很大,因为其中还有很多其他内容
  2. 表单和服务使用通用配置文件(XML,或与 #1 相同的设置对象,但序列化到磁盘)。表单只是在更改后写入对象的新副本,服务会经常检查并拾取它(如果是新的),更新其设置副本
  3. 与 #2 相同,但使用基本的 WCF 调用来告诉服务去获取设置。本质上,是#2 的“按需”版本,而不是“轮询”版本。

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

感谢您的见解!

有帮助吗?

解决方案

我有点使用你的数字2。

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

我有一个设置课,可以在我的两个程序中使用。在此设置课内我设置了 Filesystemwatcher 查看设置文件的对象。

如果设置文件由另一个应用程序更新,我的当前将获得事件触发器,以指示设置需要重新加载。

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

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

另一件事要牢记的是,在文件编写时可以锁定在文件时,因此您可以使用temp名称保存,删除旧,重命名临时方法,或在阅读后阅读时在文件上放置一些保护性锁定。 FileWatcher事件发生了更改。

我在我的 Filesystemwatcher 在进行之前

IPSDependency.FileSystem.WaitForLockOnFile(Me.mFilePath)

这样的代码就是这样。 (现在阅读本文后,我可能会有更好的方法在此处使用一些睡眠来减少CPU的thrash thrash)

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

其他提示

假设一切都在同一台机器上运行,这样怎么样:

  1. 定义一个定义设置的通用 C# 结构。所有项目都包含此 .cs 文件。将此类定义为 结构体 与一个 结构布局顺序 或者 显式的 因此它可以直接映射到非托管共享内存。例如:

    structlayout(layoutkind.sequential)]不安全的struct mySharedSettings {public int setter1;公共整数设置2;公共字符串设置3;// 在这里添加更多字段。}

  2. 使用 命名共享内存 (又名: 内存映射文件)。这允许同一台计算机上的多个进程共享数据,而不需要额外的开销 远程处理 或者 世界碳纤维. 。共享内存速度非常快,并且与管道不同,它提供对共享内存数据的随机访问。该服务将创建指定的共享内存,并且 UI 应用程序将打开该共享内存。您必须使用 pinvoke 才能使用底层 Windows API,但这并不是什么大问题。

  3. UI 应用程序将 MySharedSettings 写入共享内存,而服务则读取共享内存。

  4. 用一个 命名信号量 和/或 命名互斥体 保护对共享内存的访问并发出新设置可用性的信号。该服务有一个专用的后台线程,它只需对信号量执行 WaitOne(),并且 UI 线程将在写入新数据时发出信号。

通常,执行“投票操作”(IE同步文件)的服务在其轮询间隔中有足够的滞后时间,您可以轻松地重新阅读每个环路,甚至根据需要重新阅读所有设置。

如果您的服务更符合SOA后端的线路,那么这些更改可能会影响服务的设置,而设置通常仅在服务的一生中使用一次。如果这是您的应用程序类型,那么您上面描述的选项#2是最可靠的。我不能说我非常关心保罗的实施,因为轮询这样的文件将产生不可靠的结果。我建议使用全球命名的等待手柄来发出更改的过程。我敢肯定,您可以在这里找到一个示例。如果您不想这样做,则可以对配置文件的最后修改时间进行轮询。

总的来说,我偏爱使用注册表进行存储的第一种方法。在注册表中将所有设置以离散值的形式编写,并在您的服务中按需阅读它们。它比您想象的要快,并且易于在前端和后端实施。

我必须同意您对#2和#3的最初倾向。我特别喜欢#3,因为我不喜欢投票,但最终我认为#2或#3之间的决定将由您的服务要求驱动。

至于用户设置的存储,我建议探索孤立的存储( http://msdn.microsoft.com/en-us/library/3ak841sy.aspx )。它为对用户文件的安全,一致且可靠的访问提供了出色的机制。除非管理员完全关闭隔离存储,否则您不必担心用户已获得许可。另外,如果您启用漫游,则用户可以在同一域上使用不同的系统,甚至可以与他们进行设置,这很光滑吗?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top