דחיית חישובים בעקבות קלט משתמש

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

מה עושים? דוחים את מלאכת החישוב, ומבצעים אתה מקסימום 4 פעמים בשנייה (או כל מספר אחר, לא נתווכח על קבוע). הפתרון המוצג כאן ממומש ב-Qt4, אבל גוגל משתמשים ברעיון הזה ב-Google Suggest ב-JavaScript.

foo::foo(){
  QTimer selectionTimer;
  selectionTimer.setSingleShot(true);
  selectionTimer.setInterval(200);
  connect(&m_selectionTimer,SIGNAL(timeout()),this,SLOT(doLongCalculations()));
} 
void foo::on_keypress() // on keyboard pressed, or something if (m_selectionTimer.isActive()) m_selectionTimer.stop(); }
void foo::doLongCalculations(){ // whatever you want to do }

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

אני קבעתי את ה-timer ל-200 msec כי פרק זמן מעל 300msec זה זמן התגובה המירבי שאפשר לתת בממשק משתמש לפני שמישהו יחשוב שהתוכנית איטית. אם נשים זמן ארוך יותר התוכנית “תיראה איטית” למשתמש, וקצר יותר לא ממש עזרנו לעצמינו.

נראה שתכנות אסינכרוני הוא פתרון טוב לבעיות התגובתיות של יישומים. מסרבל את הקוד, אבל התוכנה נראית ממש “מהירה”, כאשר לא ממש שיפרתי את הקוד, אלא בסך הכל לא הגבלתי את ה-event loop באירועים ארוכים מדי.

Share Button

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *