דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. ארכיון code613m
  4. עבודה בתהליך משני (Thread / Task) ובכל זאת ה-UI תקוע

עבודה בתהליך משני (Thread / Task) ובכל זאת ה-UI תקוע

מתוזמן נעוץ נעול הועבר ארכיון code613m
34 פוסטים 4 כותבים 2.3k צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • איש אחדא מנותק
    איש אחדא מנותק
    איש אחד
    כתב ב נערך לאחרונה על ידי
    #3

    דוד ל.ט. , אתה מקיים בנו "עוד הם מדברים ואני אשמע"... :smile:

    אז בבקשה (אח, איזה נדיב שאני...)

    קטע רלוונטי מהשגרה המתבצעת בלחיצה על כפתור "בצע שאילתא":

    Private Sub btnManual_Click(sender As Object, e As EventArgs) Handles btnManual.Click  
       If BeforeQuery() = False Then Exit Sub
       If result Is Nothing OrElse result.Tables.Count = 0 Then If MsgBox("לא קיימים נתונים בטבלה זו.", הודעה) Then Exit Sub
       tblMain.DataSource = result.Tables(0)
    End Sub
    

    להלן 2 גרסאות של הקטע הרלוונטי בפונקצייה שמפעילה את התהליך, אחת ב Thread והשנייה ב Task:

    Private Function BeforeQuery() As Boolean
       Dim trd As New Thread(AddressOf query)
       trd.Start()
       pbarLoad.Visible = True
       trd.Join()
       pbarLoad.Visible = False
       Return True
    End Functionאו:
    
    Private Function BeforeQuery() As Boolean
       Dim trd As New Task(AddressOf query)
       trd.Start()
       pbarLoad.Visible = True
       trd.Wait()
       pbarLoad.Visible = False
       Return True
    End Function
    

    והקטע הרלוונטי בפונקצייה של התהליך עצמו:

    Private Function query() As Boolean
       conn.Open()
       command.Connection = conn
       command.CommandText = queryString
       dataAdapter.SelectCommand = command
       dataAdapter.Fill(result)
       conn.Close()
       Return True
    End Function
    

    תודה רבה!

    פורסם במקור בפורום CODE613 ב04/12/2017 18:26 (+02:00)

    תגובה 1 תגובה אחרונה
    0
    • dovidD מנותק
      dovidD מנותק
      dovid ניהול
      כתב ב נערך לאחרונה על ידי
      #4

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

      פורסם במקור בפורום CODE613 ב04/12/2017 19:37 (+02:00)

      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

      בכל נושא אפשר ליצור קשר dovid@tchumim.com

      תגובה 1 תגובה אחרונה
      1
      • clickoneC מנותק
        clickoneC מנותק
        clickone
        כתב ב נערך לאחרונה על ידי
        #5

        @איש-אחד
        למה שלא תשתמש בbackgroundworker?

        http://www.visual-basic-tutorials.com/Tutorials/Controls/BackGroundWorker.htm

        פורסם במקור בפורום CODE613 ב04/12/2017 21:43 (+02:00)

        אין טסט כמו פרודקשן.

        המייל שלי urivpn@gmail.com

        תגובה 1 תגובה אחרונה
        2
        • איש אחדא מנותק
          איש אחדא מנותק
          איש אחד
          כתב ב נערך לאחרונה על ידי
          #6

          תודה על התשובות / הצעות!

          @דוד ל.ט.

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

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

          רק אציין שגם ניסיתי במקום Join / Wait לכתוב את השורות הבאות, אבל התוצאה זהה - כשהשאילתא רצה העולם מת.

          Do Until trd.IsAlive = False
               If lblWait.Visible Then lblWait.Visible = False Else lblWait.Visible = True
               Thread.Sleep(250)
          Loop
          

          @ClickOne

          למה שלא תשתמש בbackgroundworker?

          למה אני לא משתמש? כי אני לא יודע שיש כזה דבר... :smile:
          והאמת, שתוך כדי גיגולים ראיתי גם את האופצייה הזו ושמתי עליה עין,
          אבל אמרתי בליבי, לפני שהפרוגרסבר - שלא דורש שום שורת קוד - עובד, מה טעם ללכת בגדולות ונפלאות ממני...

          פורסם במקור בפורום CODE613 ב04/12/2017 22:37 (+02:00)

          תגובה 1 תגובה אחרונה
          0
          • dovidD מנותק
            dovidD מנותק
            dovid ניהול
            כתב ב נערך לאחרונה על ידי
            #7

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

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

            פורסם במקור בפורום CODE613 ב04/12/2017 22:52 (+02:00)

            מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

            בכל נושא אפשר ליצור קשר dovid@tchumim.com

            תגובה 1 תגובה אחרונה
            2
            • dovidD מנותק
              dovidD מנותק
              dovid ניהול
              כתב ב נערך לאחרונה על ידי
              #8

              זה
              @איש-אחד

              אם התהליך הראשי ידליק את התהליך המשני ולא יחכה לו - אני תמיד אקבל תקלת "אין נתונים"...

              לא הבנתי. למה שתקבל תקלה אם אין שגיאה? או שאתה מדבר על מקרה שגיאה.

              פורסם במקור בפורום CODE613 ב04/12/2017 22:56 (+02:00)

              מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

              בכל נושא אפשר ליצור קשר dovid@tchumim.com

              תגובה 1 תגובה אחרונה
              0
              • איש אחדא מנותק
                איש אחדא מנותק
                איש אחד
                כתב ב נערך לאחרונה על ידי
                #9

                בס"ד

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

                אבל לדוגמא,
                תסתכל בשורה השלישית של המקטע הראשון שציטטתי - כאשר לוחצים על הלחצן של ביצוע השאילתא:

                If result Is Nothing OrElse result.Tables.Count = 0 Then If MsgBox("לא קיימים נתונים בטבלה זו.", הודעה) Then Exit Sub
                

                דהיינו, אם אין עדיין תוצאת שאילתא, או שהתוצאה היא 0 טבלאות, זרוק מסג'בוקס ותעיף החוצה.

                היות וסדר הפעולות הוא:

                1. השגרה המופעלת ע"י לחצן "בצע שאילתא", קוראת לפונקצייה beforeQuery, ומחכה לה בסבלנות בשביל להמשיך לשורה הבאה.
                2. הפונקצייה beforeQuery מדליקה את התהליך query ולא מחכה לו אלא גומרת מיד ומחזירה שליטה לשגרה "בצע שאילתא" שקראה לה.
                3. השגרה של "בצע שאילתא" ממשיכה לשורה הבאה ומחפשת מה קורה במשתנה result, אבל הוא כמובן ריק, כי התהליך שמתחבר לשרת המרוחק תמיד יהיה יותר איטי מ-2-3 משפטי קוד בתוכנית עצמה.
                4. result ריק? שלום ולא להתראות.

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

                פורסם במקור בפורום CODE613 ב04/12/2017 23:45 (+02:00)

                תגובה 1 תגובה אחרונה
                0
                • dovidD מנותק
                  dovidD מנותק
                  dovid ניהול
                  כתב ב נערך לאחרונה על ידי
                  #10

                  ההודעה שלי ממשיכה להיות רלוונטית.

                  פורסם במקור בפורום CODE613 ב05/12/2017 00:41 (+02:00)

                  מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                  בכל נושא אפשר ליצור קשר dovid@tchumim.com

                  תגובה 1 תגובה אחרונה
                  0
                  • איש אחדא מנותק
                    איש אחדא מנותק
                    איש אחד
                    כתב ב נערך לאחרונה על ידי
                    #11

                    @דוד ל.ט.

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

                    אני מבין שכנראה הדרך שמצאתי בגוגל היא לא הדרך הנכונה, ולכן אני מתקן את שאלתי מ"למה לא עובד לי" ל"איך אני עושה את זה".

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

                    *מקומם הראוי: תלוי בשגרה שהריצה את השאילתא, ותפקידה. לחצן "קבל רשימת מסדים" מריץ שאילתא SHOW DATABASES וממקם את התוצאות בליסט של מסדים. לחצן "קבל טבלאות" > SHOW TABLES > ליסט טבלאות. ולחצן "קרא טבלה" > SELECT * > דטא גריד.

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

                    ולזאת בקשתי שטוחה: אנא הדריכו אותי איך צולחים את המשימה.

                    תודה רבה!

                    פורסם במקור בפורום CODE613 ב05/12/2017 01:32 (+02:00)

                    תגובה 1 תגובה אחרונה
                    0
                    • dovidD מנותק
                      dovidD מנותק
                      dovid ניהול
                      כתב ב נערך לאחרונה על ידי
                      #12

                      @דוד ל.ט.

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

                      דרך א (בגוף התהליך המשנה לתת חיווי בשורה האחרונה שלו שהנה הוא גומר).
                      בלי BW:

                      Private uiContext As SynchronizationContext = SynchronizationContext.Current
                      
                      Private Sub BeforeQuery() 
                          Dim trd As New Thread(AddressOf query)
                          trd.Start()
                          pbarLoad.Visible = True
                      End Function
                      
                      Private Sub AfterQuery()
                          pbarLoad.Visible = False
                          ...
                      End Sub
                      
                      Private Sub query()
                          conn.Open()
                          Command.Connection = conn
                          Command.CommandText = queryString
                          dataAdapter.SelectCommand = Command()
                          dataAdapter.Fill(result)
                          conn.Close()
                          uiContext.Post(AddressOf AfterQuery, Nothing)
                      End Sub
                      

                      עם BW, הכי פשוט זה להוסיף אותו לטופס בדיזיינר ופשוט לשים באירועים שלו את הקודים.

                      דרך ב (Task + Await).

                      Private Async Sub QueryAsync()
                          pbarLoad.Visible = True
                          Await Task.Run(AddressOf query)
                          pbarLoad.Visible = False
                          ...
                      End Sub
                      
                      Private Sub query()
                          conn.Open()
                          Command.Connection = conn
                          Command.CommandText = queryString
                          dataAdapter.SelectCommand = Command()
                          dataAdapter.Fill(result)
                          conn.Close()
                      End Sub
                      

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

                      פורסם במקור בפורום CODE613 ב05/12/2017 01:57 (+02:00)

                      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                      בכל נושא אפשר ליצור קשר dovid@tchumim.com

                      תגובה 1 תגובה אחרונה
                      1
                      • איש אחדא מנותק
                        איש אחדא מנותק
                        איש אחד
                        כתב ב נערך לאחרונה על ידי
                        #13

                        ראשית כל, תודה על התשובה והדוגמאות!

                        @דוד ל.ט.

                        דרך א'

                        Private Sub AfterQuery()
                            pbarLoad.Visible = False
                            ...
                        End Sub
                        

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

                        זה בדיוק העניין,

                        היות ולאחר השאילתא כל פעם הטיפול אחר לגמרי, פעם זה לאכלס דטא גריד X ופעם ליסטבוקס Y, פעם לצעוק על מסד ריק ופעם על טבלה ריקה,
                        אז זה יהיה טיפשי להכניס הכל לשגרה אחת של "אחרי התהליך", ולהתחיל לעבור עם if-else או case על כל האפשרויות השייכות -
                        כאשר למעשה בכל שגרה שמזמינה ביצוע שאילתא מסוימת (לחצן טען מסדים, לחצן טען טבלאות, לחצן הצג טבלה) אפשר בקלות להגדיר את טיפול ההמשך הרלוונטי לשגרה זו בלבד.
                        ולכן חשבתי לשאול, האם יש דרך לקרוא לתהליך מתוך שגרה, לחכות עם החזרת השליטה עד לאחר גמר ביצוע התהליך, ולהמשיך את אותה השגרה.

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

                        תודה רבה!

                        פורסם במקור בפורום CODE613 ב05/12/2017 03:00 (+02:00)

                        תגובה 1 תגובה אחרונה
                        0
                        • dovidD מנותק
                          dovidD מנותק
                          dovid ניהול
                          כתב ב נערך לאחרונה על ידי
                          #14

                          אני מבין שאתה רוצה בדרך הא' לשלוח פרמטר כל פעם למודת המשך אחרת. זה אפשרי בקלות, אלא שאני חושש להתאמץ בלי להיות בטוח בתכנון שלך.
                          אני מבין/משער/מנחש שהתודות Query וגם BeforeQuery הם גנריות. ויש מתודות רבות שקוראים להם כל אחת עם שאילתה שונה ועם טיפול המשך שונה. כמו"כ אני משער שתמיד הערך הנדרש אחרי הביצוע הוא DataSet. האם אני צודק?

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

                          פורסם במקור בפורום CODE613 ב05/12/2017 03:14 (+02:00)

                          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                          בכל נושא אפשר ליצור קשר dovid@tchumim.com

                          תגובה 1 תגובה אחרונה
                          0
                          • איש אחדא מנותק
                            איש אחדא מנותק
                            איש אחד
                            כתב ב נערך לאחרונה על ידי
                            #15

                            אכן צדקת - ישנן מתודות שונות שקוראות למתודות הגנריות "beforeQuery" ו- "query", וממשיכות כל אחת בצורה אחרת,
                            אם כי ספציפית ה-DataSet מתמלא כבר בתוך מתודת השאילתא "query" הגנרית, מכיון שהוא באמת נדרש בכל המתודות.
                            אבל עדיין יתכן טיפול שונה בין המתודות גם לא לאחר DataSet - במידה והשאילתא נתקעה.
                            שאז לדוגמא, מתודה אחת תצעק אין מסדי נתונים, בעוד שהשניה תצעק שאין נתונים בטבלה.

                            לגבי הדרך הב',
                            אם מתודת ה Async רק מפעילה עם Await את מתודת השאילתא ובזה היא סיימה את עבודתה,
                            והמתודות שקוראות למתודת ה-Async הן אלו שממשיכות את הטיפול - חזרנו לאותה בעייה, שהן ממשיכות מיד ולא מחכות (בדקתי את זה).
                            ואם אני כותב את משפטי הטיפול שלאחר השאילתא בתוך מתודת ה Async (איפה שסימנת את 3 הנקודות בתור המיקום להמשך הטיפול),
                            שוב חזרנו לבעייה שהמשך הטיפול אמור להיות שונה בין המקרים.

                            **תודה רבה!**אני מקווה שאני לא גורם לך נדודי שינה עם ה"קלוץ קאשעס" שלי 😉

                            פורסם במקור בפורום CODE613 ב05/12/2017 03:30 (+02:00)

                            תגובה 1 תגובה אחרונה
                            0
                            • dovidD מנותק
                              dovidD מנותק
                              dovid ניהול
                              כתב ב נערך לאחרונה על ידי
                              #16

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

                              Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
                                  RunQuery("SELECT  8 FROM BIG_TABLE", Sub(ds)
                                                                              If ds.Tables.Count = 0 OrElse ds.Tables(0).Rows.Count = 0 Then
                                                                                  MessageBox.Show("!!!")
                                                                              Else
                                                                                  DataGridView1.DataSource = ds.Tables(0)
                                                                              End If
                                                                          End Sub)
                              End Sub
                              
                              Private Async Sub RunQuery(command As String, doAfter As Action(Of DataSet))
                                  pbarLoad.Visible = True
                                  Dim ds = Await Task.Run(Function() query(command))
                                  pbarLoad.Visible = False
                                  doAfter(ds)
                              End Sub
                              
                              Private Function query(command As String) As DataSet
                                  conn.Open()
                                  command.Connection = conn
                                  command.CommandText = queryString
                                  dataAdapter.SelectCommand = command()
                                  Dim ds As New DataSet
                                  dataAdapter.Fill(ds)
                                  conn.Close()
                                  Return ds
                              End Function
                              

                              אפשר לעשות אותו רעיון עם אפשרות א'. אבל אפשרות ב' היא יותר נוכנה כיום, אז למה לא נלך איתה וזהו.
                              שים לב שקצת שיניתי פה כמה דברים כי פשוט אני לא יכול לכתוב לפי הראש שלך בלי לראות הכל, והכי טוב שאתה תכתוב לפי הראש שלי 🙂

                              פורסם במקור בפורום CODE613 ב05/12/2017 03:36 (+02:00)

                              מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                              בכל נושא אפשר ליצור קשר dovid@tchumim.com

                              תגובה 1 תגובה אחרונה
                              2
                              • איש אחדא מנותק
                                איש אחדא מנותק
                                איש אחד
                                כתב ב נערך לאחרונה על ידי
                                #17

                                בס"ד

                                הפעם זה כבר נשמע מעניין ממש,
                                רק שהעיניים שלי נעצמות מאליהן... :roll:

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

                                תודה רבה!!!

                                פורסם במקור בפורום CODE613 ב05/12/2017 03:54 (+02:00)

                                תגובה 1 תגובה אחרונה
                                0
                                • איש אחדא מנותק
                                  איש אחדא מנותק
                                  איש אחד
                                  כתב ב נערך לאחרונה על ידי
                                  #18

                                  בס"ד

                                  ובכן, הרעיון להכניס ללמבדה את כל "המשך הטיפול" ולשלוח אותה למתודת ה-Async כארגומנט - אכן עושה את העבודה. תודה רבה!

                                  וברשותך ר' @דוד ל.ט., שתי שאלות שנולדו לי בעקבות הפתרון:

                                  **א.**בדוגמא שהכנת, אתה יוצר את ה-DataSet מתוך פונקציית תהליך המשנה, ומחזיר אותו למתודת ה-Async.
                                  האם לאחר שמתודת ה Async סיימה את פעילותה, עדיין אוכל לגשת ל DataSet לצורך בדיקה אם השתנו בו דברים, ואם כן לעדכן אותם במסד?
                                  כי איך שאני עשיתי עד עכשיו, הגדרתי את ה DataSet כמשתנה גלובלי בשם result, ודרכו תיקשרתי עם המסד - מכל מתודה בתוכנה, כגון:

                                  dataAdapter.Update(result) ' לשמירת השינויים שנעשו בדטה גרידאו:
                                  
                                  If result.GetChanges IsNot Nothing Then ' מציע למשתמש לשמור שינויים לפני הפעלת שאילתא חדשה
                                  

                                  ב. האם יש דרך להשתמש במתודת ה-Async כפונקצייה במקום שגרה, בכדי שאוכל להחזיר ערך בוליאני שיודיע על כשל באמצע?
                                  כמובן שתמיד ניתן ליצור משתנה גלובלי שיקבל false בתחילת השגרה וישתנה ל true בסופה, אבל בשביל זה יש פונקצייה, לא? 😉
                                  ניסיתי להגדיר את ה-Async כפונקצייה מסוג Task(Of Boolean), ולבדוק במתודה שקראה לה את תוצאת ה AsyncQuery.Result,
                                  אבל כשזה מוגדר כך, אז פונקציית ה Async נתקעת ולא ממשיכה - בשלב שהתהליך שהיא מריצה מסיים את פעולתו.

                                  תודה רבה!!!

                                  פורסם במקור בפורום CODE613 ב05/12/2017 22:42 (+02:00)

                                  תגובה 1 תגובה אחרונה
                                  1
                                  • dovidD מנותק
                                    dovidD מנותק
                                    dovid ניהול
                                    כתב ב נערך לאחרונה על ידי
                                    #19

                                    בקשר לא', כתבתי לך
                                    @דוד ל.ט.

                                    שים לב שקצת שיניתי פה כמה דברים כי פשוט אני לא יכול לכתוב לפי הראש שלך בלי לראות הכל, והכי טוב שאתה תכתוב לפי הראש שלי 🙂

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

                                    בקשר לב', היית יכול לעשות ככה:

                                    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
                                    	RunQuery("SELECT  8 FROM BIG_TABLE", Sub(hasSuccess)
                                    											 If Not hasSuccess Then
                                    												 'error
                                    											 Else If result.Tables.Count = 0 OrElse result.Tables(0).Rows.Count = 0 Then
                                    												 MessageBox.Show("!!!")
                                    											 Else
                                    												 DataGridView1.DataSource = result.Tables(0)
                                    											 End If
                                    										 End Sub)
                                    End Sub
                                    
                                    Private Async Sub RunQuery(command As String, doAfter As Action(Of Boolean))
                                    	pbarLoad.Visible = True
                                    	Dim ds = Await Task.Run(Function() query(command))
                                    	pbarLoad.Visible = False
                                    	doAfter(ds)
                                    End Sub
                                    
                                    
                                    Private Function query(command As String) As Boolean
                                    	conn.Open()
                                    	command.Connection = conn
                                    	command.CommandText = queryString
                                    	dataAdapter.SelectCommand = command()
                                    	Try
                                    		dataAdapter.Fill(result)
                                    	Catch
                                    		Return False
                                    	End Try
                                    	conn.Close()
                                    	Return True
                                    End Function
                                    

                                    אבל אני חושב שזה לא טוב לעשות ככה. לפעמים תצטרך לדעת את השגיאה ועוד.
                                    תוכל לעשות try מסביב למתודה האסינכורנית (הAwait) או לנהל את השגיאה בתוך התהליך ולשלוח את השגיאה בתוצאה (באובייקט שמכיל גם Exception). אבל באמת אני לא יודע מה הRight Way בהתנהלות מול שגיאות בasync.

                                    פורסם במקור בפורום CODE613 ב05/12/2017 23:36 (+02:00)

                                    מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                                    בכל נושא אפשר ליצור קשר dovid@tchumim.com

                                    תגובה 1 תגובה אחרונה
                                    1
                                    • dovidD מנותק
                                      dovidD מנותק
                                      dovid ניהול
                                      כתב ב נערך לאחרונה על ידי
                                      #20

                                      אני מאוד השתעבדתי לצורת הפעולה שלך, אם הכל היה תלוי בי הייתי עושה ככה:

                                      Dim dataSet As DataSet
                                      
                                      Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
                                      	UiBefore()
                                      	Try
                                      		Dim result = Await Query("SELECT  8 FROM BIG_TABLE")
                                      		dataSet = result
                                      		If result.Tables.Count = 0 OrElse result.Tables(0).Rows.Count = 0 Then
                                      			MessageBox.Show("!!!")
                                      		Else
                                      			DataGridView1.DataSource = result.Tables(0)
                                      		End If
                                      	Catch ex As Exception
                                      		'erro
                                      	End Try
                                      	UiAfter()
                                      End Sub
                                      
                                      Private Function query(command As String) As DataSet
                                      	Using conn As New SqlConnection
                                      		Using da As New SqlDataAdapter(command, conn)
                                      			conn.Open()
                                      			Dim ds As New DataSet
                                      			da.Fill(ds)
                                      			Return ds
                                      		End Using
                                      	End Using
                                      End Function
                                      
                                      Private Sub UiBefore()
                                      	pbarLoad.Visible = True
                                      End Sub
                                      Private Sub UiAfter()
                                      	pbarLoad.Visible = False
                                      End Sub
                                      

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

                                      פורסם במקור בפורום CODE613 ב05/12/2017 23:56 (+02:00)

                                      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                                      בכל נושא אפשר ליצור קשר dovid@tchumim.com

                                      תגובה 1 תגובה אחרונה
                                      3
                                      • איש אחדא מנותק
                                        איש אחדא מנותק
                                        איש אחד
                                        כתב ב נערך לאחרונה על ידי
                                        #21

                                        תודה על תשובתך!

                                        בקשר לב',
                                        דווקא לשגיאות בתוך התהליך כבר עכשיו זה מנוהל מתוך מתודת התהליך עצמו,
                                        אבל עיקר השאלה ששאלתי זה למקרה של עצירת מתודת ה-Async עוד לפני שהיא מגיעה לשלב של התהליך.

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

                                        עד ש"העלית אותי" על ה-Async, עשיתי את זה עם הפונקצייה BeforeQuery, שבמידה והיא נפלה באמצע - היא החזירה false.
                                        השאלה אם יש דרך דומה להגדיר גם את מתודת ה-Async כ"פונקצייה", או אולי דרך אחרת בכלל?

                                        תודה רבה!!!

                                        פורסם במקור בפורום CODE613 ב06/12/2017 00:00 (+02:00)

                                        תגובה 1 תגובה אחרונה
                                        0
                                        • איש אחדא מנותק
                                          איש אחדא מנותק
                                          איש אחד
                                          כתב ב נערך לאחרונה על ידי
                                          #22

                                          אני רואה שאנחנו עובדים בצורה אסינכורנית, תוך כדי שאתה כתבת תגובה חדשה - אני כתבתי תגובה לתגובתך הקודמת. :lol:

                                          וואו, הרעיון שהעלית בתגובתך האחרונה - הוא אדיר, וכמובן שהוא מייתר לגמרי את תגובתי הקודמת שנכתבה לפני שראיתי את הרעיון שלך.

                                          תודה רבה!!!

                                          אגב,@דוד ל.ט.

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

                                          פורסם במקור בפורום CODE613 ב06/12/2017 00:38 (+02:00)

                                          תגובה 1 תגובה אחרונה
                                          1

                                          • 1
                                          • 2
                                          בא תתחבר לדף היומי!
                                          • התחברות

                                          • אין לך חשבון עדיין? הרשמה

                                          • התחברו או הירשמו כדי לחפש.
                                          • פוסט ראשון
                                            פוסט אחרון
                                          0
                                          • דף הבית
                                          • קטגוריות
                                          • פוסטים אחרונים
                                          • משתמשים
                                          • חיפוש
                                          • חוקי הפורום