c# شرح - كيف يمكنني الانتقال إلى مؤشر ترابط واجهة المستخدم لتحديث واجهة المستخدم أثناء إجراء المعالجة المجمعة في تطبيق وينفورم؟




windows form (9)

لتفصيل ما يقوله الناس حول دويفنتس، وهنا وصف لما يمكن أن يحدث.

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

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

على سبيل المثال، أثناء حفظ البيانات، يمكن للمستخدم القيام بأشياء مثل جعل التطبيق تظهر مربع حوار مشروط غير مرتبط تماما بالمهمة الطويلة (مثل المساعدة -> حول). أنت الآن تتفاعل مع إجراءات المستخدم الجديدة داخل المهمة قيد التشغيل منذ فترة طويلة. سوف دويفنتس العودة عند الانتهاء من كافة الأحداث التي كانت تنتظر عند استدعائها، ثم تستمر مهمة تشغيل طويلة.

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

ما يحدث هنا هو أن Application.DoEvents يجعل إعادة الدخول البرمجية الخاصة بك. انظر تعريف ويكيبيديا هنا . لاحظ بعض النقاط من الجزء العلوي من المقال، أن رمز ليكون إعادة الدخول، فإنه:

  • يجب عدم الاحتفاظ ببيانات ثابتة (أو عالمية) غير ثابتة.
  • يجب أن يعمل فقط على البيانات المقدمة إليه من قبل المتصل.
  • يجب ألا تعتمد على الأقفال لموارد سينجليتون.
  • يجب عدم استدعاء برامج الكمبيوتر غير المعاد إدخاله أو الروتين.

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

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

لدي وينفورمز التطبيق المكتوب في C # مع. نيت 3.5. تشغيل عملية دفعة طويلة. أريد التطبيق لتحديث حالة ما تقوم به عملية دفعة. ما هي أفضل طريقة لتحديث واجهة المستخدم؟


كان دويفنتس () ما كنت أبحث عنه ولكن لقد صوتت أيضا حتى الإجابات الخلفية لأن ذلك يبدو وكأنه حل جيد أنني سوف التحقيق في بعض أكثر من ذلك.


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

Control.Invoke متزامن (ينتظر حتى يعود المندوب). إذا كنت لا تريد الانتظار يمكنك استخدام .BeginInvoke() إلى قائمة الانتظار فقط الأمر.

و .BeginInvoke() من .BeginInvoke() يسمح لك للتحقق مما إذا كانت الطريقة المكتملة أو الانتظار حتى الانتهاء.


و باكغروندوركر يبدو وكأنه الكائن الذي تريده.


Application.DoEvents () أو ربما تشغيل الدفعة على مؤشر ترابط منفصل؟


الطريقة السريعة والقذرة تستخدم Application.DoEvents() ولكن هذا يمكن أن يسبب مشاكل مع الأحداث ترتيب يتم التعامل معها. لذلك فمن غير المستحسن

المشكلة ربما لا يكون لديك لإخراج إلى مؤشر الترابط واجهة المستخدم ولكن يمكنك القيام المعالجة على مؤشر الترابط واجهة المستخدم حظره من التعامل مع الرسائل. يمكنك استخدام مكون باكغروندوركر للقيام المعالجة دفعة على مؤشر ترابط مختلف دون حظر مؤشر ترابط واجهة المستخدم.


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

لعرض التحديثات، أشرطة التقدم أو نص شريط الحالة هما من النهج الأكثر شيوعا.

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


استخدم Backgroundworker ، وإذا كنت تحاول أيضا تحديث مؤشر ترابط واجهة المستخدم الرسومية من خلال التعامل مع الحدث WorkerReportsProgress=true (مثل، WorkerReportsProgress=true )، تأكد أيضا تعيين WorkerReportsProgress=true ، أو مؤشر الترابط الذي يتم الإبلاغ عن التقدم سيموت في المرة الأولى التي يحاول للاتصال ReportProgress ...

يتم طرح استثناء، ولكن قد لا ترى ذلك إلا إذا كان لديك 'عندما ألقيت' تمكين، والإخراج تظهر فقط أن خرج مؤشر الترابط.


تحرير : هذا الآن جزء من MoreLINQ .

ما تحتاجه هو "متميز" بفعالية. لا أعتقد أنه جزء من LINQ كما هو ، رغم أنه من السهل الكتابة:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>
    (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> seenKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (seenKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

لذلك ، للعثور على القيم المميزة باستخدام خاصية Id ، يمكنك استخدام:

var query = people.DistinctBy(p => p.Id);

ولكي تستخدم خصائص متعددة ، يمكنك استخدام أنواع مجهولة ، والتي تقوم بتنفيذ المساواة بشكل مناسب:

var query = people.DistinctBy(p => new { p.Id, p.Name });

غير مجربة ، ولكن يجب أن تعمل (والآن على الأقل يجمع).

فإنه يفترض المقارن الافتراضي للمفاتيح على الرغم من ذلك - إذا كنت ترغب في تمرير في مقارنة المساواة ، فقط تمريرها إلى منشئ HashSet .







c# .net winforms