برنامجك أكثر تجواباً أكثر تفاعلاً مع BackgroundWorker - نسخة قابلة للطباعة +- منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب (http://vb4arb.com/vb) +-- قسم : قسم لغة الفيجوال بيسك VB.NET (http://vb4arb.com/vb/forumdisplay.php?fid=182) +--- قسم : قسم مقالات VB.NET (http://vb4arb.com/vb/forumdisplay.php?fid=184) +--- الموضوع : برنامجك أكثر تجواباً أكثر تفاعلاً مع BackgroundWorker (/showthread.php?tid=4692) |
برنامجك أكثر تجواباً أكثر تفاعلاً مع BackgroundWorker - RaggiTech - 01-10-12 كاتب الموضوع : مهند بيسك أوغلو
بسم الله الرحمن الرحيمالسلام عليكم ورحمة الله وبركاته... أنا اسمي مهند وهيبة, جديد على هذا المنتدى الرائع..فأحببت أن أشارك في هذا الموضوع المتواضع لا أعرف إن كان الموضوع قد طُرح سابقاً, ولكن سأتوكل على الله وابدأ بالموضوع . ============================================ BackgroundWorker عبارة عن مكون موجود في نطاق الأسماء: System.ComponentModel.BackgroundWorker لماذا استخدم BackgroundWorker ؟ لنفترض أن لديك برنامج يقوم البحث بين الملفات ولكن مهمة البحث ليست الغرض الأساسي من البرنامج فهناك العديد من المهام التي يمكن للمستخدم أن يقوم بها ,فهل من المعقول أن ينتظر المستخدم انتهاء عملية البحث حتى يقوم بتصفح مهام برنامجك الأخرى؟؟ وخصوصاً أن عملية البحث هذه تأخذ وقتاً طويلاً من الانتظار! أن واثق من استخدامك للأسلوب السابق سيفقد احترام المستخدمين لبرنامجك , وأول عملية سيقوم بها بعد TaskManager سهي إزالة جذور برنامجك من حاسوبه!!! بل الأسوأ من ذلك :بافتراض أن العملية هي عملية نسخ أو حذف ملفات ضخمة لن يستجيب برنامجك لضغطات زر الفأرة على زر "إلغاء الأمر"!!إنها بلا شك مصيبة ضخمة!وأزيد من المصائب مصيبة(جعلها الله مجرد مصائب برمجية لنا ولكم) وهي مشكلة واجهة المستخدم UI التي ستصبح صمٌ بكمٌ عميٌ بدون استخدام BackgroundWorker ============================================ BackgroundWorker في الخدمة بعد هذه المقدمة الطويلة المملة ! قد تكون عرفت المشكلة وخطورتها والآن هيا نتوكل على الله ونبدأ بتعلم BackgroundWorker . أولاً: إضافة BackgroundWorker إلى مشروعك تستطيع إضافة هذا المكون برمجيا عن طريق إنشاء نسخة منه ومن ثم قنص أحداثه بواسطة AddHandler أو WithEvents على مزاجك. وهناك طريقة أسهل منها وهي من قائمة الأدوات في قسم Components ومن ثم أضفه إلى المشروع. ============================================ مثال : برنامج قبل BackgroundWorker لكي تذوق جمال BackgroundWorker يجب عليك أن تعرف كيف كانت الحال قبله فعلى سبيل المثال:لدي نافذة Form وفيها Progressbar و زر "إلغاء الأمر" بكل بساطة يقوم البرنامج بزيادة قيمة ال"Value" لل" Progressbar " عند الضغط على زر "ابدأ" أما الزر "إلغاء الأمر" فإنه يقوم بإعطاء قيمة " Cancelled" = trueوبعد الانتهاء من العملية يظهر النتيجة على عنوان النافذة أي إذا تم إلغاء العملية أو لا. ابدأ مشروع جديد أضف إلى النافذة : o ProgressBar rg o Command Button :cmdCancel o Command Button:cmdStart o BackgroundWorker:BGW و إليك الكود كاملاً: كود : Public Class Form1 آمل ألا تصادفك مشاكل عند تجربة الكود, على كل حال بعد أن تشغل البرنامج وتضغط على الزر cmdStart يبدأ ProgressBar بزيادة قيمته والآن حاول خلال الزيادة أن تضغط زر cmdCancel أو حاول تحريك النافذةَ! النتيجة أكيد سيئة جداً !! ولكن أطمئنك هذه الحالة ستزول إن شاء الله بعد استخدامك للBGW أو BackgroundWorker لنبدأ أولاً بفهم الكود من الأول وإجراء التعديلات اللازمة: نلاحظ أن عندنا 3 إجراءات: o AddValue: يقوم بإسناد قيمة ال ProgressBar عن طريق المتغير i o : DoSomeWork يقوم بحلقة دوران عند بداية كل دورة يتأكد من Cancelled و يستدعي الإجراء AddValue o FinallyWork : يظهر النتيجة المناسبة حسب قيمة Canceled و بالنسبة إلى الزر : CmdStart يقوم باستدعاء الإجراءين DoSomeWork,FinallyWork أما الزر CmdCancel يقوم بإسناد قيمة Cancelled إلى True هذا هو الكود بكل بساطة. ...والآن سيدخل BGW إلى الساحة فلنر ما هي التعديلات التي سنقوم بها ============================================ وإليك الكود كاملاً: كود : Public Class Form1 نأتي الآن إلى الإجراء DoSomeWork ماذا سنفعل!!سنستبدل كل الكلام المكتوب فيه بجملة واحدة هي BGW.RunWorkerAsync() ماذا تفعل هذه الجملة السحرية ؟! بكل بساطة تقوم باستدعاء الحدث BGW_DoWork الذي يقوم بالعمل الثانوي إن كان بحث عن ملفات أو تحميل ملف من الانترنيت أو تعامل مع قاعدة بيانات ....الخ إذا فحلقة الدوران التي كتبناها في الإجراء DoSomeWork سنكتبها هنا مع إجراء بعض التعديل نسيت أن أقول لك أن تسند قيمة BGW.WorkerSupportsCancellation = True و ذلك من أجل أن تدعم إمكانية إلغاء العملية نرجع إلى BGW_DoWork , للتحقق من أن العملية تم إلغائها أم لا سنضع جملة الشرط التالية : كود : If BGW.CancellationPending = true Then الجواب:هو الإجراء البسيط BGW.CancelAsync() سؤال ثاني: لماذا أسندت قيمة Cancel إلى True ؟ مالفائدة منها؟؟ الجواب: سترى الجواب في السطر التالي هناك حدث آخر أريد أن أعرفك عليه ! وهو الحدث BGW_RunWorkerCompleted , ولكن متى يستيقظ هذا الحدث!؟ يستيقظ أو يحدث في هذه الحالات o إتمام العملية:أي وصل تنفيذ البرنامج إلى السطر End Sub في الحدث BGW_DoWork o إلغاء العملية: أي عندما نسند قيمة e.Cancel إلى True في الحدث BGW_DoWork o حدوث خطأ :مثل أن تستدعي الإجراء BGW.RunWorkerAsync()بينما BGW.isBusy=True إذاً من المنطقي أن نستدعي الإجراء BGW. CancelAsync() من خلال الحدث CmdCancel_Click حتى لا تختلط عليك الأمور بالنسبة لإلغاء العملية :أعرض عليك هذا الملخص البسيط: 1- حتى تتمكن من إلغاء العملية التي تعمل في الخلفية يجب عليك إسناد قيمة BGW. WorkerSupportsCancellation إلى True 2- حتى تجعل CancellationPending إلى True يجب أن تستدعي الاجراء BGW. CancelAsync 3- في الحدث BGW_DoWork يجب عليك أن تتأكد من قيمة CancellationPending فإذا كانت True اجعل e.Cancel=true 4- لتعرف إذا كانت العملية تم إلغاءها أم لا فعليك بالحدث BGW_RunWorkerCompleted من خلال الخاصية e.Cancelled المتعلقة بالخاصية e.Cancel المشار إليها في البند السابق ولكن مهلاً أين كود تعديل قيمة ProgressBar ؟ يسعدني ان اقول لك أن هذا الكود انتقل مع عائلته الكريمة إلى الحدث ProgressChanged ليصبح الكود هكذا: AddValue(e.ProgressPercentage) ..أوه !! ماهذا الشيء الغريب الذي بين القوسين؟؟!!؟! إنه يا عزيزي المبرمج نسبة التقدم المئوية إني لا أطلب منك يامهند الترجمة بل أطلب إليك ما معناه في البرمجة! اوه...حسناً أريد ان أقول لك لو كان عندك كود ينسخ ملفات من مجلد فبماذا ستتعلق قيمة النسبة المئوية؟ أكيد..بعدد الملفات المنسوخة إلى عدد الملفات الكلية.وكذلك الحال بالنسبة لكود تحميل ملف أو بحث في قاعدة بيانات, أما في برنامجنا الحالي ستتعلق بعدد دورات الحلقة المئة أي بعد كل دورة سيزيد ProgressPercentage مقدار 1 ولكن متى سينطلق الحدث ProgressChanged ؟ مثل بساطة انطلاق الحدث DoWork سينطلق هذا الحدث عند استدعاء الطريقة BGW.ReportProgress التي تتطلب وسيطة واحدة من نوع Integer , أما أين سنستدعي هذه الطريقة ؟ في الحدث BGW_DoWork وهكذا يصبح الحدث BGW_DoWork بشكل كامل: كود : For i As Integer = 0 To 100 ======================================== خاتمة... "ربنا لا تؤاخذنا إن نسينا أو أخطأنا" ليس هناك موضوع لا أخطاء وخاصة إذا كان كاتب هذا المقال من المبتدئين في عالم الدوت نيت فلذلك أرجو أن تستقبلوا موضوعي بصدر رحب وإن كنت قد أضعت وقتك في هذا المقال فأرجو أن تسامحني وأنا أعتذر منك أشد الاعتذار أما إذا شعرت أنك قد استفدت ولو بشيء قليل فما أطلب منك إلا أن تقول لي "جزاك الله خيراً " فتكون قد بالغت في العطاء ...أخوك:مهند وهيبة .....والله ولي التوفيق |