في الموضوع السابق تحدثت عن القائمة البريدية الحمقاء و كيف أنها فشلت عند أول تجربة تشغيل قاسية لها، و تحدثت عن مشكلتها الصغيرة (: عند تعبئة جدول Outgoing_Emails بالرسائل التي يجب إرسالها لجميع المشتركين،،،الحمد الله المشكلة تم حلها الأسبوع الماضي و تم إرسال رسالة لجميع المشتركين أمس و لم ننسى أحداً،،و الذي قمت به بإختصار عبارة عن عملية تغيير لكود التعبئة بحيث يقوم بإدخال الرسائل في جدول Outgoing_Emails على مراحل بإستخدام تقنية الـ Paging، و هي بشكل مختصر تعمل بالطريقة التالية:يتم قراءة البريد الإلكتروني لأول 100 مشترك ثم اسجل رسائلهم في جدول Outgoing_Emails ثم انتقل للـ 100 مشترك الذين يتلونهم، و هكذا.....،، كل هذا يتم في جملة تكرار for-loop صغيرة....وهو بصراحة حل بسيط و فعال، و هو أول حل جاء في بالي و لكن كنت اخاف ان لا أنتهي منه بسرعة، خصوصاً و أن المدة الذي سيستغرقها اختبار الكود أكبر من المدة التي سأستغرقها في برمجته،،،على ايه حال،، و لله الحمد انتهيت منه و قد قام بحل المشكلة بشكل مرضي، و لم يستغرق ذلك الكثير من الوقت، خصوصا انني لم أتعب نفسي كثيرا في اختباره D: و أعتمدت على ان الكود السابق كان يعمل بشكل جيد، و لكن للأسف هذه الحل أظهر لي مشكلة كانت موجودة في كودي السابق لا أعتقد ان احداً لاحظها،، و هي تسبب إرسال الرسالة أكثر من مرة لنفس المشترك، طبعاً للاسف لم انتبه لها إلا بعد فوات الأوان، و بعد امتلاء بريد المشتركين بنسخ مكررة بنفس الرسالة!و المشكلة بإختصار تكمن في الفنكوشة SendQueudEmail، حيث أنها تسمح بتنفيذ نفسها أكثر من مرة، و كان من المفترض ان لا أسمح بتنفيذ الفنكوشة SendQueueEmail في نفس الوقت أكثر من مرة، بكلام آخر كان يجب ان أجعلها Serialized Function، بحيث أنها عندما تبدأ في التنفيذ و تكتشف انه يوجد مسلك آخر Thread يقوم بتنفيذها يجب ان ترجع، و تؤجل تنفيذها، و هذه مشكلة تصنف في عرف المبرمجين ضمن أخطاءالتزامن Synchronization Bug، و من سيفهمه سيعرف لماذا يكرة المبرمجين برمجة التطبيقات المتعددة المسالك Multithreading Application و يقولون أنها معقدة!.المشكلة بإختصار حتى لا أصيبكم بالضجر هي ان الفنكوشة SendQueuedEmail ستسغرق في التنفيذ مدة طويلة بحيث أن المدة المحددة Interval في المؤقت Timer سوف تنقضي و يتم تنفيذ مسلك Thread جديد لتنفيذ هذه الفنكوشة :).... بمعنى،، أن الفنكوشة SendQueuedEmail سوف يكون لها مسلكان thread يعملان في نفس الوقت لإرسال نفس الرسالة لنفس المشتركين، لأنني ببساطة أقوم بحذف الرسالة من جدول Outgoing_Email في نهاية الفنكوشة، و هذا الكود لا يتم تنفيذه إلا بعد إنشاء المسلك الجديد :) ....هذه المشكلة أخذت مني قرابة الساعة لأكتشفها، و قد جائتني الكثير من الشتائم بسبب وصول الرسائلة أكثر من مرة في بريد المشتركين، و أحُس بأني تهزءت بسببها، لكن ما أقول إلا ربنا على الظالم! الشكل التالي توضيح للمشكلة:و هذا هو الكود الجديد للفنكوشة بعد التعديل:
public enum Serialized { Executing, NotExecuting } // متغير جديد لضبط التزامن private static Serialized_sync = Serialized.NotExecuting; public static void SendQueuedMail() { string SmtpServer = EmailProvider.Instance().SmtpServer; string UserName = EmailProvider.Instance().UserName; string Password = EmailProvider.Instance().Password; int Port = EmailProvider.Instance().Port; EnumEmailFormat format1 = EmailProvider.Instance().EmailFormat; int emailPerCycle = EmailProvider.Instance().EmailsPerCycle; int maxAttempts = EmailProvider.Instance().EmailAttempts; ArrayList sentEmails = new ArrayList(); ArrayList failedEmails = new ArrayList(); if (_sync == Serialized.Executing) return; try { _sync = Serialized.Executing; // نفس كود الإرسال القديم ..... } finally { _sync = Serialized.NotExecuting; } }