
הטקסט המלא של הדקות הראשונות בהרצאה «Managing Resources - חלק 1» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
אחרי שראינו מה זה garbage collector וראינו שהgarbage collector הוא זה שאחראי על הקצאת מקום בזיכרון וגם על שחרור המקום בזיכרון אנחנו עוברים לנושא שנקרא managing resources קודם כל בואו ניתן הגדרה ל-resource resource בעברית משאב זה בעצם כל רכיב פיזי או וירטואלי בתוך המחשב שיש לו זמינות מוגבלת זאת אומרת
שאנחנו צריכים כשאנחנו משתמשים איתו יש לנו זכות להשתמש איתו סבבה אבל בסיום השימוש אנחנו צריכים להחזיר אותו למערכת בכדי שעוד תוכנות ועוד לקוחות ועוד מערכות יוכלו להשתמש בו.
משאב יכול להיות קשור לזיכרון יכול להיות קשור ליכולת עיבוד נתונים לקוח של המעבד הוא יכול להיות קשור לקבצים הוא יכול להיות קשור לתקשורת נתונים.
וכל אחד מהנושאים האלה יכול להיות איזשהו משאב שאנחנו יכולים להשתמש בו, וכשאנחנו מסיימים אנחנו צריכים לפגור אותו ברוב המקרים. בואו ניקח דוגמה.
אם לדוגמה אנחנו רוצים להשתמש באיזושהי סטרינג, אז כל מה שאני עושה, אני יוצר לעצמי איזושהי מחרוזת, אני יכול להשתמש איתה, להכניס לתוך הערך, להציג אותה.
בסיום השימוש בה אני לא צריך להחזיר את המחרוזת הזאת לשום מקום. היא ניתנה לי, יש לי פה איזשהו תא זיכרון שאני יכול להכניס לתוכו מחרוזת, אין לי בעיה של מקום בזיכרון כרגע, זה לא נקרא ריסורס, כי יש לי יחסית כמות גדולה של אפשרויות לפתוח
תאי זיכרון כאלה, ואני לא צריך להחזיר אותם לאף אחד בסיום השימוש. בואו ניקח דוגמה אחרת שהיא כן דוגמה של ריסורס.
אנחנו פותחים אובייקט שנקרא StreamWriter. סטרים רייטר אנחנו יודעים שזה בעצם מאפשר לנו לכתוב לקבצי טקסט. ניקח פה רייטר ונפתח פה איזשהו קובץ c.2 myfile.txt writer.write ומה שעשינו עכשיו ופתחנו קובץ לצורך כתיבה.
זה כן נחשב ריסורס. למה? מפני שמי שנתנו את הזכות להשתמש עם הקובץ זאת מערכת ההפעלה וברגע שהיא אמרה לנו אין בעיה אני מאפשרת לכם ליצור פה איזשהו קובץ ולהשתמש איתו אז היא דואגת לזה שאף תוכנה אחרת כולל אנחנו לא נוכל לפתוח את הקובץ הזה בזמן שהוא פתוח על ידינו זה אומר שאנחנו צריכים
בסיום השימוש לסגור את הקובץ בכדי לשחרר אותו שמישהו אחר יוכל להשתמש איתו או אפילו שאנחנו בתוכנה שלנו נוכל עוד פעם במהלך התוכנה לפתוח אותו לקרוא ממנו לכתוב אליו זאת הסיבה שקובץ לדוגמה נחשב ריסורס ולכן הרכיב סטרים רייטר נחשב ריסורס, נחשב איזשהו משאב או יותר דיוק הרייטר הזה נחשב איזשהו משאב מסוג הסטרים רייטר.
סיימנו לכתוב, אנחנו צריכים ללכת לבצע רייטר נקודה ואנחנו רואים לדוגמה שיש לנו פה פונקציית קלוז שאומרת סיימתם בואו תסגרו את הקובץ ובזה שחררתם את המשאב.
עכשיו אם אני מסתכל על מה זה באמת זה סך הכל איזשהו משתנה אובייקט מסוים שאני פותח אותו משתמש בו ובסיום השימוש אני רוצה לסגור אותו. אז אם אני מסתפק עם אובייקטים יש לי רק שני מקומות שבהם אני יכול להגדיר אובייקטים או שאני מגדיר אובייקט כdata member של איזושהי מחלקה יש לנו פה איזושהי מחלקה a ואנחנו מגדירים אובייקט מבחינתנו resource כרגע.
אז בואו ניקח את זה ונשים אותו פה. או שיש לנו פונקציה ובתוך הפונקציה אנחנו יכולים גם כן להשתמש עם איזשהו משאב. זאת אומרת יש לנו שתי אפשרויות להגדיר ריסורס שזה סך הכל משתנה מסוג אובייקט כלשהו או שהוא data member של מחלקה או שהוא משתנה לוקאלי בתוך פונקציה.
למה אני מראה את שתי השיטות האלה או שני המקרים השונים האלה? מפני שהטיפול בריסורס הוא שונה עבור כל אחד מהם. אין לנו יותר מקומות שבהם אנחנו יכולים להגדיר משתנה בתכנות, לפחות ב-C-Sharp, או שאתה Data Member של מחלקה, או שאתה משתנה בתוך פונקציה.
בשפות אחרות היו עוד כל מיני מקומות, לדוגמה, יכלתם לפתוח איזשהו משתנה באזור נקי לגמרי שנקרא מודול בשפה של Visual Basic לדוגמה. אבל אין לנו את הדברים האלה כרגע ב-C-Sharp, ולכן אנחנו מתעסקים רק עם או Data Member או משתנה לוקאלי בתוך פונקציה.
וכאמור הטיפול בכל אחד מהם הוא שונה. אז בואו נסתכל איך אנחנו באמת מטפלים בשני המקרים האלה. אז מה שנעשה זה ניקח קודם כל את הטיפול במצב שהריסורס שבו אנחנו משתמשים איתו הוא data member של מחלקה.
בואו ניקח stream writer ונבנה מחלקה שנקראת logger. logger זאת מחלקה שבדרך כלל אתם תרצו לבנות, שמאפשרת לכם לכתוב כל מיני דברים לקובץ טקסטואלי במהלך התוכנית בשביל לעקוב אחרי כל מיני דברים שקרו בתוכנית, בעיקר לצורכי דיבאגינג, לדעת מה המשתמש עשה במהלך פעילות התוכנית.
ואנחנו רוצים ברגע שנוצר אובייקט מהלוגר לפתוח איזשהו קובץ טקסטואלי בכדי לכתוב אליו במהלך חיי הלוגר.
אבל כמובן אנחנו רוצים בסיום העבודה עם הלוגר לאפשר לסגור את ה-resource. אחד הדברים החשובים שצריך לבכור בנוגע לעבודה עם resources זה סיימנו לעבוד איתו אנחנו חייבים לסגור אותו אם אנחנו לא נסגור אותו יהיה לנו משהו לא בסדר עם התוכנית או לוגית אף אחד לא יוכל לעבוד עם אותו קובץ
או אותו resource או שפתאום הוא זולל לנו המון המון זיכרון ולא שחררנו או שהוא זולל לנו המון מאבד ולא שחררנו אותו אנחנו צריכים להיפטר מ-resources ברגע שאנחנו לא רוצים להשתמש בהם יותר.
אז בואו נשנה פה כמה דברים בכדי שזה יהיה באמת לוגר אמיתי. יש לנו פה קודם כל הרשאה דגישה פרייבט. אנחנו רוצים להגדיר קובץ שנקרא לוגר.לוג. נהוג בדרך כלל שהסיומות יהיו לוג, זה גם כן קובץ טקסטואלי לחלוטין.
בגלל שזה משתנה פרייבט נתחיל איתו עם underline. זה אומר שאם מישהו יוצר אובייקט מהמחלקה לוגר, אוטומטית אנחנו מצביעים על הקובץ הזה שאפילו כדאי לשלוח פה true עבור pending.
אנחנו רואים שאנחנו לא רוצים לדרוס את הלוג הקודם שנרשם, אנחנו רוצים להוסיף אליו, ואנחנו רוצים לאפשר איזושהי פונקציה שתכתוב מידע לקובץ. יש לנו פה public, יש לנו void right ואנחנו יכולים לקבל איזושהי סטרינג, מסג', אנחנו רוצים לכתוב אותה לתוך האובייקט writer עם התאריך והשעה הנוכחיים, כדי שנדע מה המשתמש בדיוק עשה,
באיזה שעה זה היה, באיזה תאריך זה היה, הנה ההודעה שאנחנו רוצים לכתוב וכך אנחנו יכולים ברחבי התוכנית כל הזמן להשתמש עם אובייקט לוגר לכתוב מידע לקובץ הזה ואז אם יש איזושהי בעיה אנחנו יכולים להגיד למשתמש לשלוח אלינו את הקובץ אנחנו יכולים להיכנס אליו ולקרוא את הקובץ הזה ברימוט דסטופ או משהו כזה לראות מה בעצם המשתמש עשה.
עכשיו בוא נניח שיש לנו פה איזושהי פונקציה do work הפונקציה הזאת עושה איזושהי עבודה ואנחנו רוצים במהלך הפונקציה לכתוב ללוג. אוקיי, אז בואו נפתח את הלוגר. ברגע שעשינו את השורת קוד הזאת, זה אומר שיצרנו אובייקט מהלוגר, וכעת נוצר לנו האובייקט הזה מיידית שמצביע על הקובץ logger.log בכונן ה-C.
הוא כמובן נפתח במצב של אפנדינג, ואנחנו יכולים להוסיף ללוג הקודם. בסדר, אז מה אנחנו צריכים לעשות כרגע? אנחנו צריכים להתחיל לכתוב לוגר נקודה right, בואו נכתוב שבשעה הזאת בדיוק אנחנו מבצעים starting do work, שנדע שהמשתמש עשה איזה משהו, הפונקציה הזאת התחילה.
בואו נכתוב כאן ending do work, אין בעיה, בסדר גמור. אוקיי, עכשיו אם אני קורא לדו וורק, מבצע פה console read line בתוכנית, מבצע קומפילציה, נריץ, אנחנו רואים ש-DoWork ביצעה את מה שהיא ביצעה, ובואו ניכנס לקונן C, נחפש את הקובץ הזה.
יש לנו פה את קונן C, הנה הקובץ, logger.log, נפתח אותו, הוא ריק לגמרי. מה, לא כתבתי לתוכו? בהחלט כתבנו, אבל לא סגרנו אותו.
זוכרים? אמרנו, במידה ואנחנו מסיימים להשתמש עם איזשהו ריסורס, חשוב לסגור אותו.
עכשיו, כשהתוכנית הסתיימה, אז במקרים מסוימים היא סוגרת אוטומטית resources. את זה אפילו היא לא סגרה, שימו לב שאפילו התוכנית הסתיימה ולא כתבנו שום דבר לקובץ.
למה לא כתבנו שום דבר לקובץ? כי לא סגרנו את ה-resources. אז כל מה שאנחנו מראים כרגע זה שאם אנחנו משתמשים במשהו שנחשב resource, אנחנו צריכים לסגור אותו בפיום השימוש בו.
שנייה לפני שאני מראה איך אנחנו סוגרים אותו לפני שאנחנו בסיום השימוש בו, חשוב לבצע הבדלה בין ריסורס לבין זיכרון של אובייקטים שהגארבג' קולקטור מנהל. כי הרבה פעמים אנשים טועים וחושבים שזיכרון שהגארבג' קולקטור מנהל, זאת אומרת זיכרון של אובייקטים נחשב ריסורס ואנחנו צריכים לסגור אותו בעצמנו.
זה היה נכון בשפת C ובשפת C++ ובכל כל מיני שפות ישנות שאין להן garbage collector. בדוטנט קיים garbage collector שדואג במקומנו לשחרור הזיכרון של האובייקטים reference types שהוא מייצר.
לכן אנחנו לא צריכים לבגור שום דבר שקשור לזיכרון. כאשר אני מדבר על resources שאנחנו צריכים לסגור אותם בסיום השימוש בהם, אני לא מדבר על שחרור אובייקטים שהgarbage collector מבצע.
אני מדבר על כל מיני אובייקטים שאנחנו משתמשים איתם בתוכנית, שנחשבים resource מבחינת מערכת ההפעלה ומבחינת גורמים אחרים במחשב, ואנחנו חייבים לסגור אותם בכדי להחזיר אותם למערכת.
אחת מהדוגמאות שאנחנו מתעסקים איתם עכשיו זה קובץ. אתם פותחים קובץ, עליכם לסגור את הקובץ. דאטאבייס, אתם פותחים קישור לדאטאבייס, אתם צריכים לסגור אותו בכדי לשחרר את הקישור הזה.
ריקווסט לאיזשהו אתר, אתם יוצרים איזשהו ריקווסט בשביל לגלוש לאיזשהו אתר, עליכם לסגור את הריקווסט בכדי לשחרר את האתר אינטרנט או לשחרר את התקשורת לאתר, או ליתר דיוק ריספונס, קיבלתם תשובה מאיזשהו אתר,
אתם צריכים לשחרר את התשובה בסיום השימוש בה. ויש עוד המון דוגמאות גם בתקשורת נתונים, גם בקבצים, גם בהארדיסק, חמשתם עם איזושהי תמונה שזוללת המון זיכרון, אולי אתם צריכים לשחרר אותה בשביל להחזיר אותה למערכת.