PracticU

Tasks - חלק 2

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

Tasks - חלק 2
השיעור ממשיך את עבודת ה-Task ומכסה שלושה נושאים: ביטול Task באמצע הפעילות, קונספט של Child Task, וטיפול בחריגות שנזרקות מתוך Task.
ביטול Task
1. CancellationTokenSource: אובייקט שמאפשר לבקש ביטול. מחזיקים אותו במקום שנגיש גם למיין וגם לפונקציה שרצה ב-Task.
2. Cancel ו-IsCancellationRequested: מהמיין קוראים ל-Cancel אחרי לחיצת מקש. בתוך הפונקציה בודקים את IsCancellationRequested בכל איטרציה, ויוצאים מהלולאה באופן טבעי.
3. הבחנה: הפונקציה לא נהרגת בכוח. היא מסיימת את הלולאה בעצמה ומחזירה את התוצאה שחושבה עד אותה נקודה.
Child Task
4. הקשר בין Task לילד שלו: כשמפעילים Task בתוך Task אחר, אפשר להגדיר TaskCreationOptions.AttachedToParent. אז ה-Task הפנימי נחשב Child של ה-Task החיצוני.
5. המתנה להורה: ה-Task החיצוני לא נחשב מסתיים עד שכל ה-Children שלו מסתיימים. כשמחברים את Child למשל עם השהיה של שתי שניות, המיין ממתין לשניהם.
6. בלי AttachedToParent: ההורה מסתיים ב-Wait שלו, והילד ממשיך לרוץ לבד. זה ההבדל המעשי בין שתי האפשרויות.
חריגות בתוך Task
7. חריגה נבלעת: אם Task זורק חריגה, היא לא מופיעה מיד. היא מופיעה כשקוראים ל-Wait או ל-Result.
8. AggregateException: המערכת עוטפת את החריגה ב-AggregateException, והחריגה המקורית נמצאת ב-InnerException.
9. עץ של חריגות: אם יש כמה Child Tasks שזורקים חריגות, נוצר עץ של AggregateException בתוך AggregateException.
10. Flatten: הפונקציה Flatten הופכת את העץ לרשימה שטוחה. עוברים על InnerExceptions בלולאה, ומטפלים בכל חריגה לפי סוגה, למשל DivideByZeroException או IndexOutOfRangeException.
שילוב של ביטול, ילדים וחריגות נותן מבנה ברור לניהול Task מורכב.
השיעור הבא בקורס: Tasks - חלק 3

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

  1. 00:00

    ביטול Task באמצע פעילות

  2. 00:43

    שימוש ב-CancellationTokenSource

  3. 02:58

    מהו Child Task

  4. 05:55

    מדידת זמן עם Stopwatch

  5. 07:06

    הפעלת Task מתוך Task אחר

  6. 09:12

    המתנה ל-Tasks פנימיים

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

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

  1. 00:03

    ונפתח פרויקט חדש שהמטרה שלו יהיה לבטל task באמצע הפעילות. יש לנו פה file new project, נדביק את זה במקום ה-main, נגדיר מרחבי שמות, יש לנו את המרחב שמות של ה-task ושל ה-thread ואנחנו מוכנים להדגים את הדוגמה.

  2. 00:39

    לצורך ביטול task אנחנו יכולים להשתמש במשהו שהשתמשנו גם בעולם ה-threading וזה אובייקט מטיפוס cancellation token source. בואו ניקח אותו פה, נקרא לו cts ונבנה אובייקט חדש ממנו.

  3. 01:00

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

  4. 01:25

    אם ביקשו ביטול, כמובן לצאת מהפונקציה בצורה טבעית. אז בואו ניקח לדוגמה את ההפעלה של הטאסק. יש לנו פה ביצוע פעולה מסוימת, וכאן בואו נניח אנחנו נגדיר console.readline ברגע שהיוזר הולך ללחוץ על מקש אז אנחנו הולכים לעבור את ה-readline ואז נבצע cts.cancel.

  5. 01:58

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

  6. 02:15

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

  7. 02:48

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

  8. 03:06

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

  9. 03:21

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

  10. 03:40

    בואו ניקח Task T, בואו נקרא לזה t1 ונפעיל את dowork1 כאן אנחנו רוצים לבצע משהו אחר וכאן אנחנו רוצים לבצע המתנה לt1 בואו נציג כאן end of main נבנה את dowork1 כמובן שהיינו יכולים לעשות את dowork1 ככזאת שמקבלת אובייקט או שמחזירה איזשהו ערך זה אותו הדבר וכאן אנחנו רוצים לבצע איזושהי הוראה של starting do work hat נלך לישון שנייה ו-ending

  11. 05:01

    do work hat כעת יש לנו כאן איזה שהיא task שהפעילה פונקציה אחת בלבד והפונקציה הזאת האחת והיחידה לוקח לה שנייה להתבצע מה אנחנו הולכים לראות אם אנחנו מריצים את התוכנית קודם כל יש לנו הגדרה של הטאסק שמצביעה על do work hat אנחנו מתחילים את הטאסק ובאותו הזמן ממשיכים ומדפיצים את ה-continue with ממתינים את השנייה במהלך השנייה הזאת אנחנו

  12. 05:34

    יכולים לראות את שתי הדפסות האלה ויש לנו פה את הסיום של המיין בואו נריץ את זה ונראה בדיוק את מה שציפינו לקבל continue with the main לאחר מכן starting do work מפני שזה התבצע במקביל למיין ending do work ו-end of main עכשיו השאלה היא אם אנחנו נשים על כל הסיפור הזה בדיקה של זמנים בואו ניקח כאן את top watch ויש לנו פה התחלה של הבדיקה וכאן יש לנו את

  13. 06:20

    הסיום שלה. stopwatch נקודה ונראה כמה הtotal time היה stopwatch.elapsed milliseconds נריץ וזה לקח פחות או יותר שנייה יש לנו פה כל מיני דברים נוספים שהתבצעו אנחנו יכולים להריץ את זה עוד פעם בערך שנייה אבל מה היה קורה אם בתוך do work אחד היינו פותחים עוד task זאת אומרת do work אחד מבצעת את מה שהיא אמורה לבצע

  14. 07:17

    לוקח לשנייה אבל בתוך do work 1 נפעיל task t2. t2 הולכת להצביע על do work 2 ולהפעיל אותה. do work 2 הולכת להיות פה למטה. בעצם היא מאוד דומה ל-do work 1 ולכן אני פשוט אעשה copy paste.

  15. 07:47

    אשנה פה את השם ל-do work 2. נוריד רגע את הטאסק הפנימית. יש לנו פה הדפסה של starting do work 2. יש לנו end slip ו-ending do work 2. והפעם הסליפ יהיה שתי שניות.

  16. 08:03

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

  17. 08:23

    זאת אומרת הפונקציה wait הזאת לקח לה שנייה להמתין מפני שהיא לא ממתינה לדו-וורק 2 היא ממתינה לדו-וורק 1 בפני ש-T1 הפעילה את דו-וורק 1 ויש לנו פה T1 נקודה wait למה בעצם אנחנו צריכים להמתין לדו-וורק 2 אנחנו פה רוצים לבצע גם console.readline כי אחרת התוכנית בעצם הסתיימה והרגה איתה גם את דו-וורק 2 בואו נריץ את זה נראה עכשיו הדפסה טיפה שונה אבל הקונספט הוא אותו הדבר יש לנו כאן המתנה אך ורק

  18. 09:05

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

  19. 09:35

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

  20. 09:52

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

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

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

ההרצאה הבאה: Tasks - חלק 3

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

  • Tasks and Back Stack

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

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