פתרון ביטול מול callback¶
במצב של סימון לפני רישום, callback יכול להגיע כמעט מיד, אפילו לפני שהבנאי חזר. לכן כל המידע שהוא צריך נוצר לפני הקריאה הטבעית. הוא אינו משתמש בשדה waitHandle, שעלול עדיין להיות בשלבי מילוי, אלא רק ב־context שכבר תקף.
במצב Dispose לפני סימון, UnregisterWaitEx מנתק את הרישום וממתין לכל callback שכבר התחיל. רק אחריו TrySetCanceled מכריע את ה־Task אם לא נמסרה תוצאה. אם ה־callback הספיק למסור תוצאה, TrySetCanceled מחזיר false ואינו מחליף תוצאה שכבר פורסמה. זאת מדיניות מפורשת של ההשלמה הראשונה שמתקבלת, ולא הבטחה שכל בקשת ביטול תנצח.
בבדיקת barrier נוסיף שני events מנוהלים למצב המעבדה: entered ו־release. ה־callback מסמן entered, ממתין ל־release ואז מסיים. ה־controller ממתין ל־entered, מתחיל Dispose על worker אחר, בודק שהוא עדיין ממתין ואז מסמן release. אסור לבצע את השחרור מתוך ה־worker שכבר חסום ב־Dispose.
בממשק start/cancel/join, פעולת cancel מבקשת שינוי במסלול העבודה אך אינה מעבירה בעלות על משאבים בחזרה. ה־join מסיים את ההשאלה ומאפשר שחרור גם כשהתוצאה היתה הצלחה לפני הביטול. ה־callback שומר תוצאה פעם אחת, וה־owner משחרר operation handle פעם אחת אחרי join. במקרה join שנכשל אין הוכחה שהספרייה חדלה להשתמש ב־buffer, ולכן העדיפות היא שמירת המשאבים ודיווח על כשל תשתית על פני use-after-free.