פורסם 2010 במרץ 2215 שנים שלום לכולם, אני משתמש במחלקה שבכול פעם שהעכבר זז ממקומוהיא "מקפיצה" אירוע עם הפרמטר שמכיל את מיקום העכבר, בעיקרוןכאשר אני משתמש במחלקה באותו הליך של ה-UI הכול עובד כמושצריך ואכן כול פעם שהעכבר זז "מוקפץ" האירוע, הינה דוגמא של הקוד (הקוד לא נכון וכתבתי רק בשביל ההדגמה):Dim WithEvents MHook as MouseHookPrivate Sub Form_Load(Byval Sender as Object, SomeArgs) Handles Me.LoadMHook = New MouseHook()End SubPrivate Sub Mouse_Moved(byval ptLocat as POINT) Handles MHook.MouseMovedDebug.Writeline("Mouse Moved")End Subברגע שאני מכריז על המשתנה כ-New המחלקה אוטומטית מתחילה לעלות אירועים כשהעכבר זז, ביינתים הכול עובדנפלא, ברגע שאני מריץ את התוכנה מופיע לי בשורת ה-Debug Mouse Moved וכאן מתחילה הבעייה: ברצוני לגרום לכך שהאירועים יוקפצו להליך שונה מההליך של ה-UI,מה שחשבתי לעשות זה הדבר הבא:Dim WithEvents MHook as MouseHookPrivate Sub Form_Load(Byval Sender as Object, SomeArgs) Handles Me.LoadDim t as New Thread(Addressof InstallHook)t.Start()End SubPrivate Sub InstallHook()MHook = New MouseHook()End SubPrivate Sub Mouse_Moved(byval ptLocat as POINT) Handles MHook.MouseMovedDebug.Writeline("Mouse Moved")End Subעכשיו ברגע שהכרזתי על המחלקה כמחלקה חדשה בהליך אחר ואני מריץ את התוכנה לא מתרחש כלום כשאני מזיז את העכבר -מה שאני משער שקורה זה שלפי מה שאני מבין ההליך רץ, מתקין מכריז על המשתנה MHook כ-New וישרנסגר, כי ככה הליכים עובדים, ברגע שהוא מסיים את עבודותו הוא נסגר וכאן בדיוק הבעייה, איך אניגורם להליך לפעול בלי להיסגר ולתת למחלקה של ה-MouseHook "להקפיץ" אירועים להליך החדש?
פורסם 2010 במרץ 2615 שנים אתה מסתכל על זה לא נכון.הת'רד בו אתה מאתחל את המחלקה MouseHook לא בהכרח קשור לת'רד בו היא מקפיצה את ה-Event.להקפיץ בת'רד של ה-UI זאת דרך אחת(שדורשת שהאינסטנס של MouseHook יכיר את ה-GUI שלך באיזו שהיא צורה שמאפשרת Invoke).בקיצור, זה תלוי במימוש של MouseHook. אך סביר להניח שהמחלקה מבצעת Invoke כזה.(אפשר לבדוק את זה או באמצעות קוד, בהדפסה ב-Event של מאפייני הת'רד הנוכחי -- Thread.CurrentThread, או באמצעות הדיבגר(שמכיל חלון ת'רדס שאפשר להסתכל עליו אחרי שעצרת ב-Event))כדי לקפיץ ארועים לת'רד חדש, אתה יכול להשתמש בדרך הנאיבית(לא יעילה אך פשוטה) של פתיחת ת'רד חדש על כול Event שקופץ.או לפתוח ת'רד אחד ולהקרוא בו בו Queue של הודעות שתמלא בכול Event שקופץ, שים לב שבמקרה הזה אתה צריך לנעול את הקריאות ל-Queue(שימוש ב-SyncLock).בכול אחד מהמקרים, כדי להשפיע בחזרה על ה-GUI תצטרך לבצע Invoke(שינוי ל-GUI חייב להתבצע בת'רד של ה-GUI).
פורסם 2010 במרץ 2615 שנים מחבר שלום ותודה רבה על התשובה...!הבנתי חלק מהשיטות שהצעת ואני יוכל להקל על יישום המשימהשאני רוצה מפני שיש לי את קוד המקור של המחלקה ככה שאנייוכל לשנות אותה כרצוני, וכניראה שצורת המחשבה שלי הייתה פחות טובהמאשר לערוך את המחלקה עצמה. הסיבה העיקרית שאני רוצה לגרום לכךשהמחלקה תתייחס להליך אחר היא בגלל שברגע שהתוכנה שלילא מגיבה למשך זמן מסויים ב-Windows 7 ה-Hook מתבטל (LowLevelHookTimeOut)זאת בגלל שהתוכנה לא עיבדה את ההודעות (של תזוזת העכבר) במשך זמן מסויים.אם מסתכלים על המחלקה (שצירפתי) ניתן ליראות כול ההודעות על תזוזת העכבר מעובדות בתוך המתודה MouseProcבעיקרון מה שאני רוצה לבצע זה לגרום לכך שהמתודה הזו תרוץ בהליך ניפרד להליך של ה-UI (ה-Hook "יקפיץ" את האירועים למתודה הזו והמתודה תפעל בהליך נפרד), ככה שהיא לא תיהיה תלוייה ב-UI גם אם הוא לא יגיב היא עדיין תמשיך את העבודה שלה וככה ה-Hook לא יתבטל.האם יש דרך ליישם זאת...? בעיקרון חשבתי פשוט מאוד להחזיר על הליך חדש בתוך המתודה, אבל זה לא הפיתרון בגלל שאם ההליך של ה-UI לא יגיב לא עשיתי בזאת כלום, ההודעה עדיין תצטרך לעבור דרך ההליך של ה-UI.[attachment deleted by admin]
פורסם 2010 במרץ 2615 שנים א. אתה יכול(וכנראה גם רצוי) למנוע מהת'רד הראשי שלך להתקע לזמנים ממושכים.ב. בניגוד למה שאמרתי בהודעה הקודמת(הסתכלתי על התעוד של מיקרוסופט עכשיו), נראה שה-Event כן קורה בת'רד שמיצר את ה-Hook --מה שאומר שהרעיון הראשוני שלך כנראה יעבוד. רק תדאג שהת'רד שאתה יוצר לא יצא(או ע"י sleep בלופ או ע"י יצירת Event כולשהו והמתנה עליו)
פורסם 2010 במרץ 2615 שנים מחבר א. אתה יכול(וכנראה גם רצוי) למנוע מהת'רד הראשי שלך להתקע לזמנים ממושכים.ב. בניגוד למה שאמרתי בהודעה הקודמת(הסתכלתי על התעוד של מיקרוסופט עכשיו), נראה שה-Event כן קורה בת'רד שמיצר את ה-Hook --מה שאומר שהרעיון הראשוני שלך כנראה יעבוד. רק תדאג שהת'רד שאתה יוצר לא יצא(או ע"י sleep בלופ או ע"י יצירת Event כולשהו והמתנה עליו)האם אין דרך יותר טובה לגרום ל-Thread לא להיסגר חוץ מלהכניס אותו לתוך לולאה? בעיקרון ממה שאני מביןברגע שההליך מסיים את המשימה שנתתי לו הוא ישר נסגר, אין איזה אפשרות יותר הגיונית (כמו תכונה מסויימת)שגורמת להליך להמשיך לפעול למרות שסיים לבצע את מה שביקשתי ממנו?בעיקרון חשבתי להכניס אותו ללולאה אבל זה לא אפקטיבי כי אז היא יתקע בתוך הלולאה, זה פשוטנשמע הגיוני יותר שיש לו איזו תכונה ולא בדרכים כמו לולאות או Sleep, כי אם אני לא טועה הוא יתקע בהם.
פורסם 2010 במרץ 2615 שנים א. בעצם לא בטוח שאתה צריך להחזיק את הת'רד פתוח, רק תחזיק את ה-MouseHook כ-Member כדי שהוא לא ימחק ע"י ה-GC.ב. אם זאת תוכנית WinForm יש לך Application.DoEvents שמבצע את ה-Events שממתינים.
פורסם 2010 במרץ 2615 שנים מחבר מצטער על חוסר הידע ובאמת באמת תודה על העזרה, אך איך אני מחזיק אותו כ-Member? ומה זה אומר?והפקודה Application.DoEvents היא לא רק ל-Thread של ה-UI?
פורסם 2010 במרץ 2715 שנים א. הכונה היא להחזיק אותו בקונטקסט של המחלקה שלך, ולא בקונטקסט של הת'רד.ב. כן.
פורסם 2010 במרץ 2815 שנים מחבר החלטתי לבסוף להסיר את ה-Hook בכול פעם שאני מבצע פעולה שגורמת להליך של ה-UI לא להגיב ואחר כךלהחזיר את ה-Hook, וזה כניראה פתר את הבעיה - אבל נותרה לי שאלה נוספת ואחרונה,האם יש אפשרות לדעת מתי ה-Hook הפסיק לשלוח הודעות? (בגלל המקרה שציינתי שההליך של ה-UI לא מגיב)
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.