احتفظ بإعدادات متزامنة بين تطبيق النماذج وخدمة Windows (أو أي N-Tier ، حقًا)

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

سؤال

لديّ خدمة Windows تؤدي عددًا من الأنشطة الدورية ، وأريد تغيير إعدادات هذه الخدمة من تطبيق Windows Forms. لست متأكدًا ، مع ذلك ، حول أفضل طريقة للتأكد من أن الخدمة لديها تفضيلات المستخدم الأكثر تحديثًا فيها (كم مرة يتم تشغيلها ، وما هي المجلدات التي يجب استخدامها للأشياء ، وأي شيء آخر يمكن للمستخدم تحديده). يمكن للمستخدم تغيير الإعدادات في أي وقت ، حسب الرغبة ، وأود أن تعرف الخدمة عنها على الفور تقريبًا. فيما يلي الخيارات التي أزنها:

  1. تستخدم النموذج ومشاركة الخدمة كائن "الإعدادات" نفسه من مشروع ثالث مشترك ، ويستخدم النموذج مكالمة تحديثات WCF " قم بتحديث كل إعداد فردي ، على الرغم من أن هذا يبدو كثيرًا على مكالمات مختلفة). أستخدم حاليًا WCF للرسائل الأساسية ، ولكن يمكن أن يكون كائن الإعدادات ضخمًا ، نظرًا لوجود الكثير من الأشياء الأخرى هناك
  2. استخدم النموذج والخدمة ملف تكوين مشترك (XML ، أو نفس كائن الإعدادات من #1 ، ولكن مسلسل إلى القرص). يكتب النموذج مجرد نسخة جديدة من الكائن بعد تغييره ، والتحقق من الخدمة في كثير من الأحيان وتلتقطها إذا كانت جديدة ، وتحديث نسختها من الإعدادات
  3. مثل #2 ، ولكن مع مكالمة WCF أساسية التي تخبر الخدمة بالذهاب للحصول على الإعدادات. في الأساس ، "عند الطلب" بدلاً من إصدار "الاقتراع" من #2.

أعلم أن الأفضل هو أمر شخصي ، لكنني مهتم بأي أسباب واضحة للمحترفين أو CON لهذه الخيارات. نظرًا لأنني سأضطر إلى حفظ الإعدادات الخاصة بي بين Runnings of the Application (إعادة التشغيل ، إلخ) ، سأضطر إلى تسلسل الإعدادات إلى القرص على أي حال ، لذلك أنا أميل بالفعل نحو #2 أو #3. سأحتاج إلى مكان على القرص حيث يمكنني حفظ الإعدادات ، ولكن ربما سيعمل مجلد APPDATA بشكل جيد ، على الرغم من أن ذلك سيسمح للمسؤولين فقط بتغيير الإعدادات ، لأنهم الوحيدون الذين لديهم إذن للكتابة إلى هذا الموقع (حيث يمكن لكل مستخدم ، بما في ذلك حساب الخدمة ، قراءته).

شكرا على رؤيتك!

هل كانت مفيدة؟

المحلول

أنا كيندا استخدم الرقم 2 الخاص بك.

لكنني أعمل فقط في .NET 2 مع طلبي ، لكن لا يزال يجب تطبيقه.

لدي فئة إعدادات أستخدمها عبر برامجي 2. داخل هذه الفئة الإعدادات أقوم بإعداد أ FileSystemWatcher كائن ينظر إلى ملف الإعدادات.

إذا تم تحديث ملف الإعدادات بواسطة التطبيق الآخر ، فإن الحالي يحصل على مشغل حدث للإشارة إلى أن الإعدادات تحتاج إلى إعادة تحميل.

يمكنك أيضًا تطبيق نفس المبدأ في شاشة الإعدادات الخاصة بك ، بحيث إذا قام (الخدمة) بتطبيق أي شيء أثناء تحرير الإعدادات ، ينعكس في شاشتك.

يمكنني استخدام AppData (دليل اسم شركتي/تطبيق) لتخزين الملف.

الشيء الآخر الذي يجب وضعه في الاعتبار ، هو أنه يمكن أن يكون هناك قفل على الملف أثناء كتابته حتى تتمكن إما حرائق حدث FileWatcher التي تم إجراء تغييرات.

أنا استخدم هذا النهج في بلدي FileSystemWatcher قبل المتابعة

IPSDependency.FileSystem.WaitForLockOnFile(Me.mFilePath)

الرمز لذلك هو مثل هذا. (عند قراءة هذا الآن ، قد تكون هناك طريقة أفضل لاستخدام بعض النوم هنا لتقليل سحق وحدة المعالجة المركزية)

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 من تسلسلي أو صريح لذلك يمكن تعيينه مباشرة في الذاكرة المشتركة غير المدارة. فمثلا:

    structLayout (layoutkind.sequential)] unrity غير آمن mysharedsettings {public int setting1 ؛ الإعداد العام العام ؛ إعداد السلسلة العامة 3 ؛ // إضافة المزيد من الحقول هنا. }

  2. يستخدم تدعى الذاكرة المشتركة (الملقب ب: الملفات المخصصة للذاكرة). يتيح ذلك عمليات متعددة على نفس الكمبيوتر لمشاركة البيانات ، دون أن تكون النفقات العامة عن بعد أو WCF. الذاكرة المشتركة سريعة للغاية ، وعلى عكس الأنابيب ، توفر وصول عشوائي إلى بيانات الذاكرة المشتركة. ستقوم الخدمة بإنشاء الذاكرة المشتركة المسماة ، وستفتح تطبيقات واجهة المستخدم الذاكرة المشتركة. سيكون عليك استخدام Pinvoke لاستخدام واجهات برمجة تطبيقات Windows الأساسية ، ولكن هذه ليست مشكلة كبيرة.

  3. تكتب تطبيقات واجهة المستخدم mysharedsettings إلى الذاكرة المشتركة ، بينما تقرأ الخدمة الذاكرة المشتركة.

  4. إستخدم اسمه semaphore و/أو اسمه MUTEX لحماية الوصول إلى الذاكرة المشتركة والإشارة إلى توفر إعدادات جديدة. تحتوي الخدمة على مؤشر ترابط خلفية مخصص يقوم ببساطة بإجراء Waitone () على الإشارة ، وسيشير مؤشر ترابط واجهة المستخدم عند كتابة بيانات جديدة.

عادةً ما يكون للخدمات التي تؤدي "عملية الاقتراع" (IE Sync Files) وقت تأخر كافي في فاصل الاقتراع الخاص بهم والتي يمكنك بسهولة إعادة قراءة جميع الإعدادات في كل حلقة ، أو حتى حسب الحاجة.

إذا كانت خدمتك أكثر على غرار نهاية الخدمية الخلفية ، فقد تؤثر التغييرات على الإعدادات التي يتم استخدامها بشكل عام فقط مرة واحدة فقط أثناء عمر الخدمة. إذا كان هذا هو نوع التطبيق الخاص بك ، فإن الخيار رقم 2 الذي تصفه أعلاه هو الأكثر موثوقية. لا أستطيع أن أقول إنني أهتم كثيرًا بتنفيذ بولس لأن استقصاء ملف كهذا سيؤدي إلى نتائج غير موثوقة. أود أن أوصي باستخدام مقبض الانتظار على مستوى عالمي للإشارة إلى عمليتك للتغييرات. أنا متأكد من أنه يمكنك العثور على مثال هنا على ذلك. إذا كنت لا ترغب في القيام بذلك ، فيمكنك الاستطلاع لوقت التغيير الأخير لملف التكوين.

بشكل عام ، تفضيلي للنهج الأول باستخدام السجل للتخزين. اكتب جميع الإعدادات الخاصة بك في القيم المنفصلة في خلية التسجيل وقراءتها عند الطلب في خدمتك. إنه أسرع مما قد تظن ويسهل تنفيذه على كل من الأمام والخلفية.

يجب أن أتفق مع الميل الأولي نحو #2 و 3. أحب بشكل خاص رقم 3 لأنني لست من محبي الاقتراع ، لكنني في النهاية أعتقد أن القرار بين رقم 2 أو رقم 3 سيحركه متطلبات خدمتك.

أما بالنسبة لتخزين إعدادات المستخدم ، فإنني أوصي باستكشاف التخزين المعزول ( http://msdn.microsoft.com/en-us/library/3ak841sy.aspx ). يوفر آلية ممتازة للوصول الآمن والمتسق والموثوق بملفات المستخدم. لن تضطر إلى القلق بشأن الحصول على إذن من المستخدم ما لم يتم إيقاف التخزين المعزول تمامًا. بالإضافة إلى ذلك ، إذا قمت بتمكين التجوال ، يمكن للمستخدمين حتى أخذ إعداداتهم معهم إذا استخدموا أنظمة مختلفة في نفس المجال ، Slick Eh؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top