Thread + Delegate

nelsonyan30

New member
Thread + Delegate

שלום רב!!! יש לי אפליקציה webית בasp.net ,בדף מסויים יש כפתור שמבצע פעולה ארוכה ("הורדת קובץ גדול מהשרת") בשעת הלחיצה אני יוצר thread שמפעיל פונקציה במחלקה אחרת , לפני הפעלת ה thread אני מגדיר delegate + ManualResetEvent ,עכשיו המשתמש יכול מצידו לסגור את הדף הזה אך כמובן להשאר באפליקציה. הבעיה שלי היא שאני לא יודע באיזה דף הוא יהיה שאני אוכל לתפוס את הEvent שה Thread סיים ולהציג למשתמש הודעה? חשבתי גם על כיוון אחר , ללא delegate וללא event פשוט להפעיל תפונקציה בthread וברגע שבהיא תסיים היא תעשה response.erdirect() לדף שיפתח בקטן ויציד למשתמש הודעת סיום? אשמח לקבל ייעוץ + דוגמאות
 

Justin Angel

New member
קה פרובלמה מואי צ'יקיטה?

כהערת שוליים, לא ברור למה בחרת להשתמש ב-ManuelResetWaitHandle ולא ב-AutoResetWaitHandle יש כאן הבדלים מבחינת הטיפול האסינכרוני אחרי שה-Flag עולה (ספציפית, אם אפשר להוריד אותו או לא). בוא ננסה רגע להגדיר את הבעיה מחדש, אתה רוצה לבצע פעולה "כבדה" בשרת ולהודיע ללקוח בדפדפן כאשר היא הסתיימה. כל זה בלי לתקוע את הלקוח או השרת (כלומר, אסינכרוניות כפולה), ובתוך ההגבלה שאם הלקוח סוגר את הדפדפן או פשוט עובר דף כי לא מעניין אותו יותר אז אין למי לשלוח תגובה (עקב הגבלות של פרוטוקול HTTP). אז כן, ניתן לפתוח Thread בצד-שרת שיבצע את העבודה הקשה והארוכה. וניתן ליצור WaitHandle שיעברו את הטווח האסינכרוני וישמשו כ-Flagים ל-Thread שרשאי לדבר עם הלקוח. ואז הלקוח יכול לדגום את השרת ולבדוק מתי העבודה הסתיימה. אבל זה סיבוך משהו והמון עבודה. Microsoft AJAX עושה בדיוק את מה שאתה מבקש. AJAX מאפשר לך גישה א-סינכרונית לצד שרת למתודות ברמת הדף או ב-Webservice והוא דואג לביצוע הא-סינכרוני. דבר ראשון תתקין Microsoft AJAX מהאתר ajax.asp.net. תוסיף לדף <asp:ScriptManager>. תוסיף מתודה ב-Code Behind שלך שתבצע את העבודה בצד-שרת.
// in myPage.aspx.cs [WebMethod()] public static bool DoSomeHeavyLifiting() { // Do some very long calculations Thread.Sleep(10000); return true; }​
עכשיו תצטרך לפנות למתודה הזו בצד-שרת מתוך ג'אווה סקריפט. חלק א' יהיה להוסיף קריאה למתודה צד-שרת באמצעות לחיצה על למשל כפתור בצד-לקוח. חלק ב' יהיה לתפוס את התוצאה מהצד שרת.
// in myPage.aspx <asp:Button ID="btn1" runat="server" OnClientClick="CallPageMethod(); return false;" /> <script type="text/javascript"> function CallPageMethod() { PageMethods.DoSomeHeavyLifiting(onFinishedHeavyLifting); } function onFinishedHeavyLifting(result) { alert(result); } </script>​
מה שקיבלנו למעשה זה את היכולת לדבר עם המתודות בצד-שרת מתוך ג'אווה סקריפט צד-לקוח וכל זה קורה כברירת מחדל בצורה א-סינכרונית. עוד על תקשורת בין צד-שרת לצד-לקוח יהיה ניתן לשמוע בהרצאה שלי ב-31 לינואר כחלק מאירוע הענק של מיקרוסופט ה-Devleoper Academy. ההרשמה לאירוע ולהרצאות חינם, אך מספר המקומות מוגבל ל-2,500 איש.
 

nelsonyan30

New member
תודה ג´סטין

אני מכיר את Ajax ואני עובד איתו הרבה. בבעיה הספציפית לא יעזור לי Ajax כי הקוד הכבד שאני מפעיל בthread נוצר אחרי מספר בדיקות שאני עושה בcodeBehind כלומר הכפתור לא תמיד יפעיל לי ת thread , הבעיה נשארת בעיצומה ,גם אם הייתי משתמש בajax איך אני תופס את הevent finish של הthread אם המשתמש מצידו סגר את הדף שהפעיל את הthread אבל נשאר באתר ,יוני הצעיה הצעה של דגימות,זה נשמע לי קצת מכביד ,שיאט את האתר , אני לא רוצה לכנס לזה
 

Justin Angel

New member
../images/Emo26.gif

אם גם ככה AJAX יוצר לך התנהגות א-סינכרונית אמיתית, למה לך ליצור Thread שרק מדמה התהנהגות א-סינכרונית ועוד יוצר Blocking Threads? לפי דעתי, עדיף לבצע את הקריאה עם AJAX, ואם צריך לבצע את העבודה הכבדה גם בצורה "סינכרונית" לעבודה שהיא גם ככה "א-סינכרונית" בלי Threading.
 

Justin Angel

New member
../images/Emo26.gif

אם גם ככה AJAX יוצר לך התנהגות א-סינכרונית אמיתית, למה לך ליצור Thread שרק מדמה התהנהגות א-סינכרונית ועוד יוצר Blocking Threads? לפי דעתי, עדיף לבצע את הקריאה עם AJAX, ואם צריך לבצע את העבודה הכבדה גם בצורה "סינכרונית" לעבודה שהיא גם ככה "א-סינכרונית" בלי Threading.
 

pintyo

New member
נצל"ש לגבי הכנס

היי ג'סטין, האם ההרצאה שלך בנוגע ל AJAX תהיה בפורמט של הצגת ATLAS לשעבר (שהייתה אחלה, אני מתכוון לזו שהעברת במפגש של הפורום), או שתכלול פיצ'רים נוספים? או במילים אחרות - יש מצב שתפרסם את תתי הנושאים בהרצאה? תודה
 

ייוניי

New member
רעיון

הבעיה העיקרית שלך היא שכאשר מסתיימת העבודה הארוכה אתה נמצא במצב שבו הדפדפן "מנותק" מהאתר ואין לך למעשה Response רלוונטי לכתוב אליו. לעומת זאת אם תעביר ל thread את אובייקט ה Session, למשל, תוכל לשמור בו מידע לגבי הפעולה שהסתיימה. עכשיו מה שעליך להוסיף הוא מנגנון שיפעל בכל דפי האפליקציה וידגום במרווחי זמן קצרים את אותו משתנה ב Session שמכיר את המידע הרלוונטי ויציג הודעה - וזאת בעזרת קוד client-side כמובן. מצד שני, יכול להיות שכדאי לבצע דגימות ארוכות יותר (להריץ בכל דגימה לולאה עם Sleep בשרת) על מנת לחסוך בפתיחת חיבורים בין הלקוח לשרת. לצערי אני לא מכיר קוד מוכן שעושה את זה...
 

nelsonyan30

New member
תודה יוני

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

nelsonyan30

New member
טוב, הבהרת יפה מאוד את נקודה

מה דעתך על הרעיון, הרי לי חשוב להציג לו הודעה כל עוד הוא באפליקציה אם הוא יצא מהאפליקציה זה פחות מדאיג אותי , כרגע . שאלה :האם אפשר להכריז וליצור delegate בדף אחד ,בהמשך לבעיה שלי עם הthread שמבצע פונ' כבדה וברגע שהוא יסיים הוא יעורר event בדף אחר שתמיד פתוח כל עוד האפליקציה רצה ,סתם לדוגמא שהevent יתעורר בדף ה banner? מעבר לכך ראית דוגמא דיי טובה לכך בCodeproject שבין הייתר הוא שלוח לפונ' הthread את this מהדף הנוכחי ומשם כך הוא מפעיל את הevent finish ...לא ממש הצליח לי .. http://www.codeproject.com/csharp/workerthread.asp מה דעתך
 

ייוניי

New member
בתור התחלה

נסה פשוט ליצור thread בנקודה שבה מתחילה העבודה הארוכה (System.Threading.Thread) המכיל delegate שמבצע את העבודה ולהריץ אותו. דאג לאתחל משתנה ב Session בערך מסויים בתחילת העבודה ובערך אחר בסיומה. עכשיו צור רכיב נוסף על השרת (אולי WebService או משהו בסגנון...) שבכל פעם שפונים אליו מודיע בחזרה מה ערכו הנוכחי של אותו משתנה. בקוד client-side תוכל להפעיל מעיין לולאה של בקשות XMLHttp שדוגמות את השרת וברגע שהערך משתנה לערך הסיום תוכל להציג את ההודעה ב client-side. רק חשוב שהלולאה תרוץ בכל אחד ואחד מדפי האפליקציה... בהמשך אפשר לשפר את זה על ידי כך שבמקום לבצע לולאה ב client שהיא יקרה בתעבורת רשת אפשר להעביר (חלקית) את הלולאה לשרת כך שדוגמים פחות אבל זמן כל דגימה ארוך יותר. (כמובן שברגע שהעבודה הסתיימה השרת מחזיר response והכל מסתיים). אבל כמו שאתה מבין אין אפשרות שהקוד שרץ בשרת ייזום פעולה על הלקוח (ככה בנו את HTTP...) ולכן צריך את מנגנון הדגימות המוזר הזה...
 
למעלה