5

多くの定期的なアクティビティを実行する Windows サービスがあり、Windows フォーム アプリからこのサービスの設定を変更したいと考えています。ただし、サービスに最新のユーザー設定が含まれていることを確認する最善の方法についてはわかりません (実行する頻度、使用するフォルダー、ユーザーが指定できるその他のこと)。ユーザーはいつでも自由に設定を変更できるので、すぐにサービスに知らせてほしいと思います。私が検討しているオプションは次のとおりです。

  1. フォームとサービス共有は、3 番目の共有プロジェクトから同じ「Settings」オブジェクトを使用し、フォームは WCF の「UpdateSettings(newSettings)」呼び出しを使用して、変更があったことをサービスに通知します (または、必要に応じて、への呼び出し個々の設定を更新しますが、これはさまざまな呼び出しで多くのように思えます)。私は現在、基本的なメッセージに WCF を使用していますが、設定オブジェクトは他にもたくさんあるため、巨大になる可能性があります。
  2. フォームとサービスは、共通の構成ファイル (XML、または #1 と同じ設定オブジェクトですが、ディスクにシリアル化されています) を使用します。フォームは、オブジェクトが変更された後にオブジェクトの新しいコピーを書き込むだけで、サービスは頻繁にチェックし、新しいかどうかを選択して、設定のコピーを更新します。
  3. #2 と同じですが、サービスに設定を取得するように指示する基本的な WCF 呼び出しがあります。基本的に、#2 の「ポーリング」バージョンではなく「オンデマンド」バージョンです。

私は主観的であることを最もよく知っていますが、これらの選択の明白な賛否両論の理由に興味があります. アプリケーションの実行間 (再起動など) に設定を保存する必要があるため、とにかく設定をディスクにシリアル化する必要があるため、すでに #2 または #3 に傾いています。設定を保存できるディスク上の場所が必要ですが、おそらく AppData フォルダーは問題なく機能しますが、この場所への書き込み権限を持つのは管理者だけであるため、設定を変更できるのは管理者だけです。 (サービス アカウントを含むすべてのユーザーが読み取ることができます)。

あなたの洞察に感謝します!

4

4 に答える 4

3

すべてが同じマシンで実行されていると仮定すると、これはどうでしょうか。

  1. 設定を定義する共通のc#構造を定義します。すべてのプロジェクトには、この.csファイルが含まれています。このクラスを、StructLayoutSequentialまたはExplicitの構造体として定義して、アンマネージ共有メモリに直接マップできるようにします。例えば:

    [StructLayout(LayoutKind.Sequential)]安全でない構造体MySharedSettings {public int settings1; public int settings2; パブリック文字列設定3; //ここにフィールドを追加します。}

  2. 名前付き共有メモリ(別名:メモリマップトファイル)を使用します。これにより、RemotingWCFのオーバーヘッドなしに、同じコンピューター上の複数のプロセスがデータを共有できるようになります。共有メモリは非常に高速で、パイプとは異なり、共有メモリデータへのランダムアクセスを提供します。サービスは名前付き共有メモリを作成し、UIアプリケーションは共有メモリを開きます。基盤となるWindowsAPIを使用するには、pinvokeを使用する必要がありますが、これは大したことではありません。

  3. UIアプリケーションはMySharedSettingsを共有メモリに書き込み、サービスは共有メモリを読み取ります。

  4. 名前付きセマフォおよび/または名前付きミューテックスを使用して、共有メモリへのアクセスを保護し、新しい設定の可用性を通知します。このサービスには、セマフォでWaitOne()を実行するだけの専用のバックグラウンドスレッドがあり、UIスレッドは新しいデータが書き込まれたときにシグナルを送信します。

于 2010-07-24T01:42:11.347 に答える
3

私はちょっとあなたの番号 2 を使用します。

しかし、私は自分のアプリケーションで .NET 2 でのみ作業していますが、それでも適用されるはずです。

2 つのプログラムで使用する設定クラスがあります。この設定クラス内で、設定ファイルを参照するFileSystemWatcher オブジェクトをセットアップします。

設定ファイルが他のアプリケーションによって更新された場合、my current はイベント トリガーを取得して、設定をリロードする必要があることを示します。

設定画面にも同じ原則を適用して、設定の編集中に(サービス)他のアプリケーションが何かを更新した場合、それが画面に反映されるようにすることができます。

AppData (会社/アプリケーション名のディレクトリ) を使用してファイルを保存します。

心に留めておくべきもう1つのことは、書き込み中にファイルがロックされる可能性があるため、一時名の保存、古い削除、一時的な名前の変更方法を使用するか、ファイルの後で読み取るときにファイルに保護ロックをかけることができることです。変更が行われたことを示す filewatcher イベントが発生します。

先に進む前に、 FileSystemWatcherでこのアプローチを使用します

IPSDependency.FileSystem.WaitForLockOnFile(Me.mFilePath)

そのためのコードはこのようなものです。(今これを読むと、ここでスリープを使用して 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
于 2010-07-19T01:56:18.277 に答える
2

通常、「ポーリング操作」(ファイルの同期) を実行するサービスでは、ポーリング間隔に十分な遅延時間があり、ループごとに、または必要に応じてすべての設定を簡単に再読み取りできます。

サービスが SOA バックエンドに沿ったものである場合、変更は通常、サービスの有効期間中に一度だけ使用される設定に影響を与える可能性があります。これがあなたのアプリケーションのタイプである場合、上記のオプション #2 が最も信頼できます。そのようなファイルをポーリングすると信頼できない結果が生じるため、私は Paul の実装にあまり関心があるとは言えません。グローバルに名前が付けられた待機ハンドルを使用して、プロセスに変更を通知することをお勧めします。ここSOで例を見つけることができると確信しています。それをしたくない場合は、構成ファイルの最終変更時刻の変更をポーリングできます。

全体として、私の好みは、ストレージにレジストリを使用する最初のアプローチです。すべての設定を個別の値でレジストリ ハイブに書き込み、サービスでオンデマンドで読み取ります。思ったよりも高速で、フロントエンドとバックエンドの両方で簡単に実装できます。

于 2010-07-20T01:33:24.040 に答える
0

#2 と #3 への最初の傾倒には同意せざるを得ません。私はポーリングのファンではないので、特に #3 が好きですが、最終的には #2 と #3 の間の決定は、サービスの要件によって決まると思います。

ユーザー設定の保存については、分離ストレージ ( http://msdn.microsoft.com/en-us/library/3ak841sy.aspx ) を検討することをお勧めします。これは、ユーザー ファイルへの安全で一貫性のある信頼できるアクセスのための優れたメカニズムを提供します。管理者が分離ストレージを完全に無効にしない限り、ユーザーのアクセス許可について心配する必要はありません。さらに、ローミングを有効にすると、同じドメインで異なるシステムを使用している場合、ユーザーは自分の設定を持ち歩くことさえできます。

于 2010-07-22T21:04:42.140 に答える