איך אני יכול להפעיל EVENT שנורה מת'רד אחד בת'רד אחר ב C#? - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

איך אני יכול להפעיל EVENT שנורה מת'רד אחד בת'רד אחר ב C#?


Shlompy

Recommended Posts

יש לי אירועים שנורים מת'רד מסויים, אבל אני רוצה שהם ייקראו בת'רד שרושם את האירוע.

משהו בדומה ל INVOKE או BEGININVOKEרק שלא מעורבים פה פקדים...

אם זה משהו מסובך, האם יהיה דבילי סתם ליצור Control כלשהו (ללא כל שימוש בו) ולקשר איתו את שני הת'רדים בשביל ה INVOKE?

או שאולי יש אובייקט נורמלי שמיועד למקרה שאני מעוניין בו? על איזה סוגי אובייקטים ניתן לבצע INVOKE? ליתר דיוק, אני יותר מעוניין ב BEGININVOKE כי המטרה היא שת'רד אחד יבצע את ה EVENT בזמן שהת'רד שירה אותו ימשיך לרוץ.

תודה!

קישור לתוכן
שתף באתרים אחרים

הרי ברור ממה שכתבתי שאני יודע איך להגדיר אירועים (מן הסתם בצמוד ל DELEGATES) זו לא הייתה השאלה.

לפי מה שהבנתי לא ניתן לעשות את מה שאני רוצה, בכל מקרה נראה לי שאני פשוט אלך על Event.BeginInvoke ויבצע את האירוע בת'רד חדש...

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

תודה.

קישור לתוכן
שתף באתרים אחרים

אז אולי לא הבנתי לגמרי מה אתה רוצה לעשות.

מה רץ בכל אחד מה-THREADS האלה? ואיך יצירה של CONTROL תעזור לך? רק כדי להשתמש ב-BEGININVOKE של ה-CONTROL?

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

לגבי יעילות, אין לי מושג מה אתה מנסה לעשות וכמה EVENTS נורים.

קישור לתוכן
שתף באתרים אחרים

אני יודע ש INVOKE על פקד, גורם לאירוע לרוץ באותו תר'ד שיצר את הפקד. זה בעצם מה שרציתי לעשות, רק שכרגע התוכנה ב CONSOLE APPLICATION. אז כן, חשבתי לעשות את זה באמצעות CONTROL (למרות שאין ממשק טופס), אין שום בעיה מליצור אוביקט מהסוג הזה ולהשתמש בו רק בשביל ה INVOKE.

בנוגע לתוכנה, זה שרת שמקבל פקודות מהרבה קליינטים שונים (משחק פוקר), אני עדין צריך לשבור את הראש ולוודא שלא תהיה בעיה עם זה שכל פקודה שמתקבלת כרגע, ויורה אירוע, תתבצע בתר'ד נפרד (ע"י BEGIN INVOKE של האירוע עצמו), יכול להיות שיהיה סדר חשיבות מסויים לפקודות שמגיעות קשה לי אבל לחשוב על משהו כרגע... ואני מפחד שאני אצטרך לפתור את הבעיה הזו ע"י סינכרונים רבים בין תר'דים...

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

אולי הפתרון החכם יותר יהיה לממש מן תור של CONSUMER/PRODUCER בשביל מה שאני רוצה לבצע?

קישור לתוכן
שתף באתרים אחרים

מכיוון שפוקר זה משחק תורות, אז יכול להיות שלא תהיה לי את הבעיה הזו.

לכן גם אני מעדיף שהפקודות יבוצעו אחת אחרי השניה לפי התור, והדבר היחידי שיעבוד במקביל הוא רק ה LISTENER שמאזין , מנתח את הפקודות, ומפעיל את האירועים לת'רד שיריץ את מנוע המשחק.

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

קישור לתוכן
שתף באתרים אחרים

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

ד"א לא הבנתי למה בכלל אתה עושה את אפליקציית השרת בתור console app אלא אם זה לצרכי דיבאג בלבד, למה סתם לטעון את הזבל הזה לזכרון?

קישור לתוכן
שתף באתרים אחרים

כרגע זה ל DEBUG, כאשר הכל יעבוד פיקס אני אבנה עליו GUI.

לגבי ניקוי הת'רדים, במידה ואני משתמש ב BEGININVOKE אני מסיים את הת'רד ב AsyncCallback באמצעות EndInvoke. זה לא מספיק?

את הת'רד שמאזין לתקשורת אני מסיים בעזרת Thread.Abort().

קישור לתוכן
שתף באתרים אחרים

AsyncCallBack לא "מסיים" Thread, זאת שיטה לדלגציה. בכל מקרה אם אתה רוצה להמנע מRaceConditions בכל הנוגע לAsync אתה יכול לנסות לבנות את האפליקציה שלך על בסיס מודל WUD.

http://en.csharp-online.net/Asynchronous_Programming%E2%80%94Wait_Until_Done_Pattern

שוב, לכל מצב יש את הייתרונן והחסרונות שלו, AsyncCallBack, WUD, Polling יש לא מעט שיטות לעבוד עם ריבוי נימים..

בנוסף לפחות עד כמה שאני יודע לא פותחים תראדים נוספים על כל קליינט שמתחבר, בד"כ באפליקציית שרת החלק שאחראי על התקשורת עם כל הקליינטים הוא SingleThreaded, ואחראי על ההתקשרות עם כל הקליינטים, זה נכון בין השאר מבחינת ביצועים, , ופונקציאונליות טהורה בעבודה מול הNetwork Stack של מערכת ההפעלה(STPS), ריבוי נימים בתקשורת יכול להתבצע רק כאשר אתה עובד עם UDP טהור, צריך להתבצע רק כאשר האפליקציה שלך עושה מולטיפלקסינג.

לדוגמא כאשר אתה עובד עם ריבוי נימים בתקשורת, יכול להווצר Race Condition ב-TCP Stream עצמו, מה שיפגע בביצועים עקב זאת שיהיה לך חתיכת overhead עקב בקשות Retransmit רבות, הדבר הזה מאוד נפוץ בעיקר כאשר אנשים מנסים להמציא את הגלגל מחדש ובונים את כל ההתקשרות בMT ללא צורך(וללא חשיבה על דברים כמו TCP Sequencing), ולא אני לא אומר שאתה דווקא עשית משהו כזה. אבל במצב שיש בו מספר נימים על אותו סוקט מול לקוח, פקטת TCP N יכולה להשלח אחרי TCP N+1, עקב זאת שTCP בשונה מUDP לא "בנוי" לסדר מחדש את ה, stream, הלקוח יתעלם מהתעבורה וישלח בקשת Retransmit לשרת.

במצבים רבים כאשר עובדים בשפות עלית, ולא מטפלים בכלל בשכבת ההתקשרות מעבר ל network_namspace.soket.bindsoket_method() מאוד קשה עד בלתי אפשרי לטפל במצבים כאלה ברמת הקוד(מעבר ללעבוד נכון), במצבים שבהם הTCP\IP Stack של מערכת ההפעלה לא ממש מבין מה "לא בסדר" הוא פשוט ישלח את הפקטות שוב, מצב שיכול לסדר את "הבעיה".

אבל יש מצב גרוע עוד יותר שקורה בשפות עלית שלא מטפלות בשכבות האלה בכלל ונותנות לNetwork Stack של מערכת ההפעלה לטפל בכל עניין הSequancing, אתה מעביר 2 פקטות בסדר לא נכון, אבל אתה מעביר אותן בשכבות שמעל לשכבת הTCP\IP ונותן למ"ע לטפל בכל הבלאגן הזה, הTCP\IP Stack נותן להם TCP Sequence נכון, אבל הסדר "הלוגי" שלהם באפליקציה שלך לא נכון, מה שאומר שבמקרה הזה Retransmit בכלל לא יעזור.

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

קישור לתוכן
שתף באתרים אחרים

אוקיי תודה רבה על הסבר המפורט.

אני אעיין בלינק כשיהיה לי קצת זמן.

בכל מקרה, איך שהדברים עובדים אצלי כרגע:

1. ת'רד בודד שמאזין לכל הסוקטים (באמצעות Socket.Select())

2. ה RECIEVE מבוצע באופן סינכרוני באותו ת'רד שמאזין לסוקטים.

3. לאחר שהמידע התקבל ופוענח, הוא נורה באמצעות EVENT בצורה אסינכרונית ע"י BEGININVOKE, ששם יש את המימוש הלוגי של המשחק (קריאה לפונקציות של השולחנות וכדומה).

4. הפונקציות של השולחנות לא עושות עבודה כבדה כלשהי/המתנה ממושכת לתגובה משחקן, אלה פשוט פעולה קצרה בשולחן, כמו הימור של שחקן, לכן זמן החיים של הת'רד שמבצע את הפעולה הזו הוא קצר מאוד ןאין סיכוי שהוא יתקע בתוך לולאה או משהו ולא יסתיים. (אגב, אם כך המצב, האם יש סיבה לקרוא ל ENDINVOKE?

לגבי LOCK, כנראה שיהיו לי הרבה בהמשך אני מבין שאין מנוס מזה...

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

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

אשמח לתגובה על איך שהתקשורת עובדת כרגע.

אגב לא ממש הבנתי מה עלול לגרום ל RACE CONDITION ב TCP STREAM.

אחרי מבט קצר בלינק שהבאת לי, אני רואה שזו בעצם הצורה שמימשתי את קבלת התקשורת, רק שאת ה ENDINVOKE אני בתוך ה ASYNC CALLBACK.

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

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...