
Cancel אחרי לחיצת מקש. בתוך הפונקציה בודקים את IsCancellationRequested בכל איטרציה, ויוצאים מהלולאה באופן טבעי.TaskCreationOptions.AttachedToParent. אז ה-Task הפנימי נחשב Child של ה-Task החיצוני.Wait או ל-Result.InnerException.Flatten הופכת את העץ לרשימה שטוחה. עוברים על InnerExceptions בלולאה, ומטפלים בכל חריגה לפי סוגה, למשל DivideByZeroException או IndexOutOfRangeException.הטקסט המלא של הדקות הראשונות בהרצאה «Tasks - חלק 2» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
ונפתח פרויקט חדש שהמטרה שלו יהיה לבטל task באמצע הפעילות. יש לנו פה file new project, נדביק את זה במקום ה-main, נגדיר מרחבי שמות, יש לנו את המרחב שמות של ה-task ושל ה-thread ואנחנו מוכנים להדגים את הדוגמה.
לצורך ביטול task אנחנו יכולים להשתמש במשהו שהשתמשנו גם בעולם ה-threading וזה אובייקט מטיפוס cancellation token source. בואו ניקח אותו פה, נקרא לו cts ונבנה אובייקט חדש ממנו.
אם יש לנו גישה לאובייקט הזה, כלומר מהמיין, וגם לפונקציה יש גישה לאובייקט הזה, כרגע לצורך הדוגמה הגדרתי אותו כסטטי אבל יש שיטות אחרות, אז אנחנו יכולים להגדיר שאנחנו רוצים לבצע ביטול של הtask מתוך המיין, ובתוך הפונקציה אנחנו יכולים להגיע לאובייקט הזה ולדעת אם ביקשו ביטול או לא ביקשו ביטול.
אם ביקשו ביטול, כמובן לצאת מהפונקציה בצורה טבעית. אז בואו ניקח לדוגמה את ההפעלה של הטאסק. יש לנו פה ביצוע פעולה מסוימת, וכאן בואו נניח אנחנו נגדיר console.readline ברגע שהיוזר הולך ללחוץ על מקש אז אנחנו הולכים לעבור את ה-readline ואז נבצע cts.cancel.
בתוך הפונקציה אנחנו יכולים לבצע בדיקה עם cts.isCancellationRequested לבצע איזשהו ברייק. זאתי שיטה אחת שבה אנחנו יכולים לצאת מהפונקציה ברגע שביקשו לבטל.
אבל קודם כל אם אנחנו מריצים את זה ובאיזשהו שלב לוחצים על מקש אז אנחנו רואים שמיידית הפונקציה הפסיקה והוחזר הערך sum שחושב עד לאותה נקודה. אנחנו יכולים להמשיך את הכל, אם אין שום הגדרת עצירה באמצע והטאסק הסתיימה, בסדר, אז הטאסק הסתיימה, אז אף אחד לא ביקש לבטל אותה.
אז זאתי לפחות שיטה אחת שבה אנחנו יכולים לבצע הפסקה של טאסק באמצע הפעילות שלה. הדבר הבא שמעניין לראות בטאסקים זה קונספט שנקרא Child Task. הדבר הזה לא באמת היה לנו בעולם הטרדים.
כאשר אנחנו פתחנו טרד, ולא משנה אם הטרד הזה נפתח מתוך טרד אחר, לא היה לו שום קשר לטרד האחר שכאילו פתח אותו. והוא רץ בעצמו, וברגע שהוא הסתיים, הוא הסתיים.
בעולם הטאסקים יש לנו קונספט שנקרא Child Task. בואו נסתכל מה זה בעצם אומר. נפתח פרויקט חדש, ופה מה שאנחנו הולכים לעשות זה סדרה של טאסקים עם פונקציות, שהטאסקים כמובן מפעילים.
בואו ניקח Task T, בואו נקרא לזה t1 ונפעיל את dowork1 כאן אנחנו רוצים לבצע משהו אחר וכאן אנחנו רוצים לבצע המתנה לt1 בואו נציג כאן end of main נבנה את dowork1 כמובן שהיינו יכולים לעשות את dowork1 ככזאת שמקבלת אובייקט או שמחזירה איזשהו ערך זה אותו הדבר וכאן אנחנו רוצים לבצע איזושהי הוראה של starting do work hat נלך לישון שנייה ו-ending
do work hat כעת יש לנו כאן איזה שהיא task שהפעילה פונקציה אחת בלבד והפונקציה הזאת האחת והיחידה לוקח לה שנייה להתבצע מה אנחנו הולכים לראות אם אנחנו מריצים את התוכנית קודם כל יש לנו הגדרה של הטאסק שמצביעה על do work hat אנחנו מתחילים את הטאסק ובאותו הזמן ממשיכים ומדפיצים את ה-continue with ממתינים את השנייה במהלך השנייה הזאת אנחנו
יכולים לראות את שתי הדפסות האלה ויש לנו פה את הסיום של המיין בואו נריץ את זה ונראה בדיוק את מה שציפינו לקבל continue with the main לאחר מכן starting do work מפני שזה התבצע במקביל למיין ending do work ו-end of main עכשיו השאלה היא אם אנחנו נשים על כל הסיפור הזה בדיקה של זמנים בואו ניקח כאן את top watch ויש לנו פה התחלה של הבדיקה וכאן יש לנו את
הסיום שלה. stopwatch נקודה ונראה כמה הtotal time היה stopwatch.elapsed milliseconds נריץ וזה לקח פחות או יותר שנייה יש לנו פה כל מיני דברים נוספים שהתבצעו אנחנו יכולים להריץ את זה עוד פעם בערך שנייה אבל מה היה קורה אם בתוך do work אחד היינו פותחים עוד task זאת אומרת do work אחד מבצעת את מה שהיא אמורה לבצע
לוקח לשנייה אבל בתוך do work 1 נפעיל task t2. t2 הולכת להצביע על do work 2 ולהפעיל אותה. do work 2 הולכת להיות פה למטה. בעצם היא מאוד דומה ל-do work 1 ולכן אני פשוט אעשה copy paste.
אשנה פה את השם ל-do work 2. נוריד רגע את הטאסק הפנימית. יש לנו פה הדפסה של starting do work 2. יש לנו end slip ו-ending do work 2. והפעם הסליפ יהיה שתי שניות.
בואו נריץ את זה ונראה איך המיין בעצם מתנהג למרות שיש לנו פה הפעלה של טאסק מתוך טאסק. נריץ את כל הסיפור ושימו לב שהמיין לקח לו להסתיים במשך שנייה.
זאת אומרת הפונקציה wait הזאת לקח לה שנייה להמתין מפני שהיא לא ממתינה לדו-וורק 2 היא ממתינה לדו-וורק 1 בפני ש-T1 הפעילה את דו-וורק 1 ויש לנו פה T1 נקודה wait למה בעצם אנחנו צריכים להמתין לדו-וורק 2 אנחנו פה רוצים לבצע גם console.readline כי אחרת התוכנית בעצם הסתיימה והרגה איתה גם את דו-וורק 2 בואו נריץ את זה נראה עכשיו הדפסה טיפה שונה אבל הקונספט הוא אותו הדבר יש לנו כאן המתנה אך ורק
לפונקציה do work אחת כי אנחנו בעצם אמרנו שאנחנו רוצים להמתין לטאסק t1 ולטאסק t1 לוקח להסתיים שנייה למה אנחנו בעצם רוצים להמתין שתי שניות אז כאן יכול להיות מצב שטאסק מסוימת לצורך הפעולה שלה משתמשת בעוד טאסקים וכל השימוש הזה של הטאסקים הפנימיים קשורים לפעולה כי אולי היא גם רוצה לקבל ערך בחזרה למעשה אם היא הייתה
מקבלת ערך בחזרה היא הייתה עדיין ממתינה אבל בוא נניח אפילו שהיא לא רוצה לקבל ערך בחזרה. היא רוצה לבצע כל מיני פעולות, היא רוצה לשלוח אימיילים וכל טאסק שולח אימייל אחר או כל טאסק מדפיס משהו אחר למדפסת ואנחנו בעצם רוצים לבצע
המתנה עד שלא רק הטאסק שהפעלנו הסתיים, אלא עד שכל הטאסקים הפנימיים שהופעלו בתוך הטאסק שלנו הסתיימו. אז לצורך כך אנחנו צריכים להגדיר שהטאסק שאנחנו מפעילים זה basically child task של