ה תכנות מחשבים המונח "thread" הוא קיצור ל thread של ביצוע, בו מעבד עוקב אחר נתיב שצוין בקוד שלך. הרעיון של מעקב אחר יותר מחוט אחד בכל פעם מציג את הנושא של ריבוי משימות ורב חוטים.
ליישום יש תהליך אחד או יותר בתוכו. חשוב על תהליך כתוכנית הפועלת במחשב שלך. כעת לכל תהליך יש חוט אחד או יותר. ליישום משחק עשוי להיות קצה חוט לטעינת משאבים מהדיסק, אחרת לעשות AI ואחרת להפעלת המשחק כשרת.
ב- .NET / Windows מערכת ההפעלה מקצה זמן מעבד לחוט. כל פתיל עוקב אחר מטפלים בחריגות ואת העדיפות שבה הוא פועל, ויש לו איפשהו לשמור את הקשר השרשור עד שהוא יפעל. הקשר הנושאים הוא המידע שהחוט צריך לחדש.
ריבוי משימות עם חוטים
האשכולות גוזלים מעט זיכרון וליצור אותם לוקח קצת זמן, כך שבדרך כלל אתה לא רוצה להשתמש ברבים. זכרו, הם מתחרים על זמן המעבד. אם במחשב שלך יש מספר מעבדים, Windows או .NET עשויים להריץ כל חוט במעבד אחר, אך אם כמה שרשורים פועלים על אותו מעבד, ואז רק אחד יכול להיות פעיל בכל פעם והחלפת האשכולות אורכת זמן.
המעבד מפעיל חוט לכמה מיליוני הוראות ואז הוא עובר לחוט אחר. יש לשמור את כל רישומי ה- CPU, נקודת ביצוע התוכנית הנוכחית ואת המחסנית איפשהו עבור השרשור הראשון ואז לשחזר אותו ממקום אחר עבור השרשור הבא.
יצירת חוט
במרחב השמות. הברגה, תמצא את סוג החוט. חוט הבנאי (ThreadStart) יוצר מופע של שרשור. עם זאת, לאחרונה C # קוד, סביר יותר שהוא יעביר ביטוי למבדה הקורא לשיטה עם כל פרמטרים.
אם אינך בטוח בקשר לזה ביטויים למבדה, אולי כדאי לבדוק את LINQ.
להלן דוגמא לשרשור שנוצר ומתחיל:
באמצעות מערכת;
באמצעות מערכת. הברגה;
מרחב שמות ex1
{
תוכנית בכיתה
{
ריק סטטי ציבורי כתוב 1 ()
{
קונסולה. כתוב ('1');
חוט. שינה (500);
}
static void ראשי (מחרוזת [] args)
{
var המשימה = נושא חדש (כתוב 1);
משימה. התחל ();
עבור (var i = 0; i <10; אני ++)
{
קונסולה. כתוב ('0');
קונסולה. כתוב (משימה. בחיים? 'A': 'D');
חוט. שינה (150);
}
קונסולה. ReadKey ();
}
}
}
כל הדוגמאות שעושות זאת הוא לכתוב "1" לקונסולה. החוט הראשי כותב "0" לקונסולה 10 פעמים, כל פעם אחריו "A" או "D" תלוי אם החוט השני עדיין חי או מת.
השרשור השני פועל רק פעם אחת וכותב "1." לאחר העיכוב של חצי שניה בשרשור ה- Writ1 (), החוט מסתיים והמשימה. IsAlive בלופ הראשי מחזיר כעת את "ד".
חוט בריכה וספריית המשימות המקבילה
במקום ליצור חוט משלך, אלא אם כן אתה באמת צריך לעשות זאת, השתמש בבריכת חוטים. מ- .NET 4.0 יש לנו גישה לספריית המשימות המקבילות (TPL). כמו בדוגמה הקודמת, שוב אנו זקוקים למעט LINQ, וכן, הכל ביטויי למבדה.
משימות משתמשות ב- בריכת הברגה מאחורי הקלעים אך השתמשו טוב יותר בחוטים בהתאם למספר הנמצא בשימוש.
האובייקט העיקרי ב- TPL הוא משימה. זוהי כיתה המייצגת פעולה אסינכרונית. הדרך הנפוצה ביותר להתחיל דברים בריצה היא עם המשימה. מפעל. התחל חדש כמו ב:
משימה. מפעל. StartNew (() => DoSomething ());
כאשר DoSomething () היא השיטה שמופעלת. אפשר ליצור משימה ולא להפעיל אותה מייד. במקרה כזה, פשוט השתמש במשימה כך:
var t = משימה חדשה (() => קונסולה. WritLine ("שלום"));
...
t. התחל ();
זה לא מתחיל את השרשור עד שנקרא .Start (). בדוגמה להלן, חמש משימות.
באמצעות מערכת;
באמצעות מערכת. הברגה;
באמצעות מערכת. הברגה. משימות;
מרחב שמות ex1
{
תוכנית בכיתה
{
ריק סטטי ציבורי כתוב 1 (int i)
{
קונסולה. כתוב (i);
חוט. שינה (50);
}
static void ראשי (מחרוזת [] args)
{
עבור (var i = 0; i <5; אני ++)
{
ערך var = i;
var runningTask = משימה. מפעל. StartNew (() => כתוב 1 (ערך));
}
קונסולה. ReadKey ();
}
}
}
הרץ את זה ותקבל את הספרות 0 עד 4 בפלט בסדר אקראי כגון 03214. הסיבה לכך היא כי סדר ביצוע המשימות נקבע על ידי .NET.
יתכן שאתה תוהה מדוע יש צורך בערך var = = i. נסה להסיר אותו ולהתקשר לכתוב (i) ותראה משהו לא צפוי כמו 55555. למה זה? הסיבה לכך היא שהמשימה מציגה את הערך של i בזמן ביצוע המשימה, ולא כאשר נוצרה המשימה. על ידי יצירת חדש משתנה בכל פעם בלופ, כל אחד מחמשת הערכים מאוחסן ונאסף כהלכה.