תמיכה בריבוי תהליכים בלקוחות הדוא"ל
לקוחות דוא"ל כגון ImapClient ו‑Pop3Client מאפשרים למשתמשים להשתמש בהם בסביבת ריבוי‑תהליכים. לקוחות דוא"ל מאפשרים קיום של חיבור אחד או יותר עם השרת. לניהול קבוצת חיבורים בתוך הלקוחות משתמשים מאגר חיבורים. מספר החיבורים שניתן ליצור ולהשתמש בהם בו‑זמן מוגבל על‑ידי המאפיין CredentialsByHostClient.MaxConnectionsPerServer. ניתן להגדיר מאפיין זה לערך של 1 או יותר. כברירת מחדל, ערך זה הוא 10. תור פקודות יושם עבור החיבור לתמיכה בפעולות ריבוי‑תהליכים. הפקודות מממשות את הפעולות הפשוטות המוגדרות בפרוטוקול, כגון Noop, Authenticate וכן הלאה. המשתמש יכול להתחיל בהרצת יותר פקודות מהכמות הזמינה של חיבורים, אך הן תבוצענה רק כאשר הלקוח יוכל ליצור חיבור לביצוע הפעולה.
שיטות לשימוש בלקוחות דוא"ל בסביבת ריבוי‑תהליכים
ללקוחות דוא"ל יש את ההתנהגות הבאה:
1. במקרה שה‑MaxConnectionsPerServer = 1, הלקוח יוצר חיבור אחד, מבצע אימות והauthorization. חיבור זה נשמר במצב פעילות עד שהלקוח יושמד. כל הפעולות מתהליכים שונים מופנות לתור פקודות יחיד הממוקם בחיבור הראשי.
2. במקרה שה‑MaxConnectionsPerServer > 1, הלקוח יוצר את מספר החיבורים הנדרש, מבצע אימות והרשאה לכל חיבור. חיבור אחד שמור כחיבור ראשי. חיבור זה נשמר במצב פעילות עד שהלקוח יתבצע השמדתו. כל שאר החיבורים נוצרים ומשתלמים לפי דרישה. הכמות המרבית של חיבורים כאלה מוגדרת על ידי המאפיין MaxConnectionsPerServer, לדוגמה אם MaxConnectionsPerServer = 2, אז אחד שמור כחיבור ראשי, והחיבור השני משמש כתוספת לפעולות המבוצעות בתהליכים אחרים. באופן דומה, אם MaxConnectionsPerServer = 3, החיבור הראשון שמור כחיבור ראשי, ושניים נוספים משמשים כתוספת לפעולות בתהליכים אחרים. במצב שבו מתבקשת חיבור נוסף מתהליך חדש, וכל החיבורים כבר תפוסים, הלקוח מחכה עד שמספר החיבורים בשימוש יופחת. זהו רגע חשוב שמבהיר מדוע השמדת חיבורים נכונה כה משמעותית.
דוגמאות
המשתמש יכול לבצע פעולות בתהליכים שונים בכמה דרכים. ניתן לחלק אותן לשני סוגים:
1. המשתמש משתמש במתודות אסינכרוניות (Begin/End) המוגדרות בלקוח. במקרה זה לקוח הדוא"ל משגר תהליכים חדשים לפי הצורך. בלקוח יש תור משימות (אל תבלבלו עם תור פקודות בחיבור). משימה יכולה להתבצע אם יש חיבור זמין. כאשר מספר החיבורים בשימוש הופך לפחות מאשר ערך המגבלה, הלקוח יוצר חיבור חדש, יוצר תהליך עבור המשימה הנוכחית ומבצע אותה. דוגמה לשימוש בפעולות אסינכרוניות:
2. המשתמש יכול ליצור תהליכים באמצעות עצמים כגון Thread, ThreadPool, Task או כל עצם אחר שמיועד למטרה זו. בנוסף, המשתמש יכול להשתמש בתהליכים שנוצרו בקוד של צד שלישי. במהלך זאת, ללקוח יש שני מודלים של התנהגות
a. אם המשתמש לא ייצר חיבורים נוספים לפעולות בתהליך, כל הפעולות עבור תהליך זה יישלחו לתור הפקודות של החיבור הראשי. דוגמה לפעולות בתהליך נוסף ללא יצירת חיבור חדש, כל העסקאות מתבצעות דרך החיבור הראשי:
b. כאשר המשתמש מריץ שיטה ליצירת חיבור חדש לתהליל נוסף, תהליך זה חסום עד ששינוי ערך המquota לחיבורים חדשים יאפשר חיבור חדש. לאחר מכן נוצר חיבור חדש. חיבור זה מוגדר כחיבור ברירת המחדל לכל הפעולות בתהליך זה. לאחר שמסיימים את כל הפעולות בתהליך זה, יש לפנות את החיבור. כדי ליצור חיבורים חדשים השתמשו במתודה CredentialsByHostClient.CreateConnection. מתודה זו מחזירה אובייקט שמממש את הממשק IDisposable. לשחרור החיבור יש לקרוא למתודה Dispose. יצירת וחיסול חיבור חייבים להתבצע בתוך התהליך שבו מתבצעות פעולות הדוא"ל. ניסיון ליצור חיבור חדש בתהליך שבו נוצר לקוח הדוא"ל מוביל לשגיאה, מכיוון שתהליך זה במועד זה אינו יכול לשמש ליצירת חיבור חדש. כמו‑כן, יצירת חיבור חדש אינה אפשרית כאשר MaxConnectionsPerServer = 1. דוגמת קוד ליצירת חיבור חדש בתהליך נוסף:
המלצות
שווה לציין שאם המשתמש שולח את כל הפקודות דרך החיבור הראשי, ייתכנה מצב שבו פקודות משThreads שונים מתערבבות. על המשתמש להבין אילו פקודות תלויות ברצף שלהן ולנקוט אמצעים לסנכרון של פקודות אלו. יש גם לקחת בחשבון אפשרות לביצוע פקודות במפגשים שונים (IMAP/POP3). הפעולות שלוקחות את רוב הזמן, כגון FetchMessage, AppendMessage ו‑Send, ככל הנראה יש לבצע אותן באמצעות תהליך חדש וחיבור חדש. אך פעולות מהירות כגון Delete עדיף לבצען דרך החיבור הראשי. יש להבחין בכך שהאתחול של חיבור חדש הוא פעולה שגוזלת זמן.