PracticU

Tasks - חלק 3

בלי כתוביותעם כתוביות
PracticU › קורס תכנות מתקדם - #Advanced .NET C › Tasks - חלק 3
מילון מושגים:
לולאה - מבנה בקרה שחוזר על קטע קוד שוב ושוב כל עוד תנאי מתקיים או עבור כל פריט באוסף.
פרמטר - ערך שמועבר לפונקציה או לפקודה כקלט, ומשפיע על אופן פעולתן ועל התוצאה שהן מחזירות.
פונקציה - קטע קוד בעל שם שמבצע משימה מוגדרת, מקבל ערכי קלט (פרמטרים) ויכול להחזיר תוצאה. מאפשרת לארגן קוד ולהשתמש בו שוב.
תהליך - מופע של תוכנה שרצה בזיכרון, עם הקוד, הנתונים והמשאבים שהוקצו לה על ידי מערכת ההפעלה.
אינדקס - מבנה במסד נתונים שמאיץ חיפוש ושליפה. גם מספר המציין מיקום של איבר במערך.
מערך - מבנה נתונים שמאחסן אוסף ערכים מאותו סוג ברצף, שאפשר לגשת אליהם לפי מספר מיקום (אינדקס).
אובייקט - יחידה בתכנות מונחה עצמים שמאגדת נתונים (תכונות) ופעולות (מתודות). נוצר בדרך כלל ממחלקה המשמשת כתבנית.

Tasks - חלק 3
השיעור מציג שלוש יכולות מתקדמות של Task: שרשור של Task אחד אחרי השני, מחלקת Parallel שמריצה לולאות במקביל, ואוספים מקבילים שמחליפים רשימות רגילות.
ContinueWith
1. שרשור: ContinueWith מגדיר Task שיופעל רק אחרי שה-Task הקודם מסתיים. כך מגדירים את כל הסדרה מראש ומפעילים אותה פעם אחת.
2. העברת תוצאה: ה-Task הבא מקבל את ה-Task הקודם כפרמטר, ואפשר לקרוא ממנו את Result. כשהפונקציה הראשונה מחזירה מספר, השנייה מציגה אותו.
3. סדרה: אפשר לשרשר כמה שלבים. בהדגמה כל פונקציה רצה רק אחרי קודמתה, ומכיוון שמדובר ב-Task, כל הפעילות נשארת מאחורי התהליך הראשי.
Parallel
4. Parallel.For: מקבל אינדקס התחלה, אינדקס סיום ופעולה שמקבלת אינדקס. המערכת מחלקת את האיטרציות בין טסקים לפי העומס. הסדר אינו מובטח, ולכן לא משתמשים בו כשהסדר חשוב.
5. Parallel.ForEach: דומה ללולאת foreach, אבל הפעולה רצה על הערכים במקביל. בהדגמה עם מערך של מספרים, הערכים הופיעו בסדר אקראי.
6. Parallel.Invoke: מקבל רשימה של פונקציות ומפעיל אותן במקביל. הסדר לא מובטח.
7. MaxDegreeOfParallelism: מגדירים אובייקט ParallelOptions עם מספר מקסימלי של פעולות במקביל. בהדגמה עם שתיים נראו זוגות הדפסות.
אוספים מקבילים
8. הבעיה: רשימה רגילה (List) לא מוגנת מפני גישה מקבילה. בהדגמה שני טסקים מוסיפים 100,000 מספרים כל אחד לרשימה. התוצאה משתנה בין הרצה להרצה, ולעיתים מגיעה ל-185,000 ולא ל-200,000.
9. ConcurrentBag: אוסף שמאפשר לכמה טסקים להוסיף בו במקביל. בהחלפה של הרשימה בו התוצאה נכונה בכל הרצה.
10. סוגים נוספים: ConcurrentStack פועל כמו מחסנית (אחרון נכנס ראשון יוצא), ConcurrentQueue כמו תור (ראשון נכנס ראשון יוצא), ו-ConcurrentDictionary כמו מילון עם מפתח וערך.
כשמשתמשים בכמה טסקים על אותו אוסף, בוחרים באוסף המקבילי המתאים במקום לנעול בעצמנו.
השיעור הבא בקורס: תרגילים על Tasks

פרקי ההרצאה: Tasks - חלק 3

  1. 00:00

    שרשור Task עם ContinueWith

  2. 03:04

    התאמת פונקציה לחתימת ContinueWith

  3. 04:20

    קבלת ערך מה-Task הקודם

  4. 05:42

    שרשור סדרת מטלות ברצף

  5. 07:38

    עבודה מקבילה עם המחלקה Parallel

  6. 10:21

    שימוש ב-Parallel.For

תמלול ההרצאה: Tasks - חלק 3

הטקסט המלא של הדקות הראשונות בהרצאה «Tasks - חלק 3» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.

  1. 00:05

    היכולת הבאה שקיימת ב-Task נקראת Continue With. Continue With זה בעצם פונקציה שמאפשרת לנו להגדיר Task א', שרק כאשר מסתיימת מפעילה Task ב'.

  2. 00:26

    בואו נריץ את זה, או ליתר דיוק נפתח קודם כל פרויקט חדש. נגדיר כאן Task T1, יש לנו פה פנייה ל-Do Work 1, והפעלת ה-Task.

  3. 00:49

    לאחר מכן ממשיכים עם ה-Main, b1.wait בכדי שהתוכנית לא תיסגר. יש לנו פה static void do work 1, יש לנו פה do work 1, ואנחנו הולכים לישון שנייה, start do work 1, end do work 1, נבדוק קודם כל שזה עובד כמו שצריך, הכל עובד כמו שצריך.

  4. 01:50

    אבל מה קורה אם יש לנו גם את do work 2, ואנחנו רוצים לבצע את do work 2 רק בסיום do work 1, ואנחנו רוצים להגדיר את הכל מההתחלה. זאת אומרת לפני שבכלל התחלנו את כל התהליך אנחנו רוצים לבצע הגדרה של איזה פונקציות רצות קודם איזה פונקציות רצות אחר כך וסע להתחיל לעבוד עם הכל.

  5. 02:18

    אז מה שאנחנו הולכים לראות זה את פונקציית continue with. פונקציית continue with באה ואומרת לנו אוקיי בואו תנו לי איזושהי פונקציה שאני הולכת לקרוא לה רק כאשר אני מסתיימת בתור T1. עכשיו אנחנו יכולים לראות שהפונקציה continue with אומרת לנו שהיא מקבלת action של task זאת אומרת היא

  6. 02:50

    מקבלת action פונקציה שצריכה לקבל לסוגריים task, תכף אנחנו נראה מה אנחנו יכולים לעשות עם הtask הזאת. אם היינו נותנים את do work 2 בצורה כזאת אז אנחנו רואים שיש לנו פה בעיה כי דו-וורק 2 לא מתאימה לחתימה.

  7. 03:08

    בואו נלך ונשנה את דו-וורק 2 כך שהיא תתאים לחתימה ותקבל task, ויהיה ה-task הקודמת. למה יש את השליחה הזאת או את הבקשה לפונקציה שמקבלת את ה-task הקודמת?

  8. 03:23

    כי יכול להיות שהפונקציה שלנו צריכה משהו מה-task שכרגע התבצעה, לדוגמה את הערך המוחזר שלה. כרגע הערך המוחזר זה void, אז אין לנו מה לעשות איתו, אבל תכף נשנה את ה-void הזה ונראה איך זה פועל.

  9. 03:39

    דבר נוסף, פונקציית ה-wait לא ממתינה לטאסק הקודמת, לכן מה שנעשה זה לטאסק הבאה בתור. אז מה שנעשה זה console.readline בכדי שתהיה לנו פה איזושהי המתנה ונוכל לראות את הכל עובד בצורה סינכרונית אחד אחרי השני.

  10. 04:01

    אז בואו נראה איך זה מתבצע. אנחנו מריצים ואנחנו הולכים לראות שיש לנו כאן start work 1, do work 1 ואז end do work 1. רק לאחר מכן יש לנו פה start do work 2 ואז end do work 2. זאת אומרת הם לא התבצעו ביחד אלא רק כאשר הtask t1 הסתיימה אז בעצם היא הפעילה עוד task שביצעה את do work 2. אם הtask הראשונה הייתה גם מחזירה ערך פה נגדיר שאנחנו מחזירים

  11. 04:38

    integer נלך ל do work 1 ונגדיר שהוא מחזיר לנו איזשהו מספר אנחנו יכולים להשתמש במספר הזה בתוך do work 2. נדפיס previous task result ויש לנו פה את ה-prev task נקודה result כמובן אנחנו צריכים להגדיר את התסק הזאת פעם כאינטג'ר ויש לנו פה את ה-result נריץ נראה שרק כשהתסק הראשונה מסתיימת אז התסק השנייה מתחילה ולא

  12. 05:27

    רק זה שהיא מתחילה היא גם מקבלת את התוצאה שהתסק הקודמת החזירה והיא יכולה כמובן לבצע בשימוש כך אנחנו יכולים להגדיר סדרה של מטלות שרוצות האחת אחרי השנייה, אנחנו יכולים להמשיך ולעשות פה Continuid, Continuid, Continuid וכך לבצע סדרה של מטלות, בואו נעשה אפילו את DoWork 3 שהולכת לקבל את DoWork 2

  13. 05:55

    או ליתר דיוק את ה-Task שהפעילה את DoWork 2, בואו נראה ש-Continuid מצפה לקבל שוב פעם Action של Task, נעשה פה אפילו איזושהי החזרה של איזשהו ערך, שעדיף לעזוב את זה אפילו ולהראות גם דוגמה של פונקציה שלא מחזירה ערך.

  14. 06:24

    נשנה רק את השמות כאן, יש לנו פה do work 3. הפונקציה הקודמת לא מחזירה כלום, אז ניפטר מזה. נגדיר שאנחנו רוצים להדפיס do work 3 כאן, ויש לנו עכשיו מצב שבו ה-task t1 מפעילה את do work 1, רק כאשר היא מסתיימת היא מפעילה את do work 2, ורק כאשר זאת מסתיימת היא מפעילה את do work 3,

  15. 06:57

    בואו נריץ את כל הסיפור הזה יש לנו פה את do work אחד התחילה הסתיימה do work 2 התחילה הסתיימה ואפילו קיבלה את הפרמטר שמוחזר מ-do work 1 ואז do work 3 התחילה והסתיימה רק אחרי ש-do work 2 הסתיימה לגמרי כאן אנחנו יכולים לשרשר טאסקים אם אנחנו רוצים כך שהם לא יהיו ביחד אלא כל אחת עושה מטלה כשהיא מסתיימת מוגדרת

  16. 07:24

    מטלה אחרת הכל זה טאסקים הכל זה טרדים שנמצאים בטרד פול ויש לנו פה סדרת מטלות שיכולות להתבצע אחד אחרי השני, שאנחנו יכולים להגדיר אותם פעם אחת, להגדיר סטארט ואנחנו יודעים שכולם יתבצעו בצורה סינכרונית אחת אחרי השנייה.

  17. 07:43

    הדבר הבא שאנחנו הולכים לראות שבנוי על ידי טאסקס זאת מחלקה מעניינת מאוד שנקראת פארלל. פארלל מאפשרת לנו לבצע כביכול לולאות או סדרת פעולות שמשתמשת בתוך עצמה ב-Tasking.

  18. 08:10

    בואו נפתח פה פרויקט Parallel Example ומה שאני רוצה לעשות עכשיו זו פעולה מאוד מאוד פשוטה, אני רוצה לקחת לולאה שרצה 10 פעמים, מבצעת הדפסה של המספר I, בוא נניח באותה שורה, ומבצעת איזושהי המתנה Thread.Slip של חצי שנייה ועכשיו אם אנחנו נריץ את זה אנחנו אנחנו הולכים לראות שבעצם מוצגים לנו כל

  19. 08:46

    המספרים מ-0 עד 9 אבל המספרים האלה כמובן מוצגים בלולאה שלוקחת זמן בצורה סינכרונית אחד אחרי השני ולפי הסדר כי כל הפעילות הזאת לא התבצעה ביחד, לא התבצעה במקביל.

  20. 09:07

    אוקיי, מה קורה אם אני עדיין רוצה לבצע הדפסה של כל המספרים מ-0 עד 9 אבל לא אכפת לי הסדר או ליתר דיוק אם אתם רוצים לקחת סדרת מטלות לקחת לולאה שתבצע את כל המטלות האלה בוא נניח 100 דברים שונים שאתם רוצים לבצע אבל לא ממש אכפת לכם שכל הדברים האלה יתבצעו אחד אחרי השני לפי הסדר אם אתם רוצים שכל הדברים האלה יהיו במקביל אז כמובן כדאי

  21. 09:32

    לנו לפתוח טסקים בשביל לבצע את זה לדוגמה יכול להיות שליחת המון מיילים ביחד למה אני צריך ללכת ולשלוח מייל ולהמתין שהוא ישלח ואז ישלוח עוד מייל אין קשר ביניהם אני רוצה לשלוח בבת אחת 100 מיילים או 1000 מיילים לכל רשימת התפוצה שלי או להדפיס מספר הדפסות בבת אחת או לבצע מספר חישובים שלא קשורים אחד לשני או לגשת לדאטאבייס למאגר נתונים ולהביא המון המון נתונים ביחד שלא קשורים אחד לשני.

  22. 10:02

    אז כל פעם שאנחנו רוצים לבצע את כל הדברים האלה במקביל ויש לנו סדרת דברים שאנחנו רוצים לבצע ואנחנו רוצים לולאה במקום לקחת לולאת for רגילה בואו נשים אותה פה בהערה אנחנו יכולים להשתמש עם המחלקה parallel.

  23. 10:19

    המחלקה Parallel קיימת שוב פעם ב-System Threading Tasks והיא פותחת בתוך עצמה טאסקים בשביל להוציא לפועל את הפעילות שלנו.

  24. 10:29

    לדוגמה, Parallel 4. Parallel 4 אומרת לנו, תביאו לי את האינדקס ההתחלתי. בדיוק כאילו אנחנו לולת 4 רגילה. בלולת 4 רגילה האינדקס ההתחלתי שלנו היה 0. אוקיי, אז בואו נביא לה 0.

  25. 10:45

    לאחר מכן היא אומרת לנו, תביאו לי את האינדקס הסופי,

לקורס המלא: קורס תכנות מתקדם ב‑#C ודוט-נט

ההרצאה הקודמת: Tasks - חלק 2

ההרצאה הבאה: תרגילים על Tasks

הרצאות קשורות מקורסים אחרים

  • Tasks and Back Stack

קורסים נוספים במסלול

  • קורס WinForms - תוכנות רגילות בווינדוס
  • פרויקט מעשי ב-#C - בונים מחשבון פשוט
  • פרויקט מעשי ב-#C - ספר טלפונים
  • פרויקט מעשי ב-#C - תוכנת צייר
  • קורס ADO.NET - חיבור אתר למסד נתונים
  • קורס WCF - תקשורת למתקדמים בדוט-נט