How to ensure that async method finished work?

后端 未结 2 1949
时光说笑
时光说笑 2020-12-20 07:25

I\'m very new to threads, so my thoughts and questions might be a bit silly :)

I fill WinForm control with data from another thread, so I have to call <

2条回答
  •  遥遥无期
    2020-12-20 07:49

    This is absolutely wrong:

    treeViewWriter.Start();
    treeViewWriter.Join();
    

    Never call Thread.Join from Main Thread! because that Join freezes the application and all those BeginInvoke/Invoke never gets fully executed because the message is not handled.

    This is how BeginInvoke() actually works:

    1. It sends some WM_USER (or the like) on message loop.
    2. Main thread pops this message in Application.DoEvents() (or the like which is always called in Application.Run())
    3. Main thread executes the delegate passed to BeginInvoke()
    4. Main thread signals end of execution (by WaitHandle in IAsyncResult)
    5. EndInvoke() waits for such signal (or if IAsyncResult from BeginInvoke is never stored, it gets garbage-collected)

    So again: you eiter write it purely event-driven or do something like this:

    private bool done = false;
    void click(object, EventArgs) {
        thread.Start();
        while(!done) Application.DoEvents();
        tree.ExpandAll();
    }
    

    ADDON: Eihter use Invoke() (synchronized) and the above loop with Application.DoEvents()
    or use BeginInvoke() and call your ExpandAll the same way (through BeginInvoke() from the thread)

    ADDON2:

    private bool done;
    void click(object,EventArgs) {
        done = false; // init state
        new Thread(work).Start(); // start backgound work
        while(!done) Application.DoEvents(); // wait until done
        finish(); } // finish the job in main thread
    void work() {
        Thread.Sleep(100); // do your work
        done = true; } // signal done
    void finish() {
        whatever(); } // called on main thread
    
    void click2(object,EventArgs) {
        new Thread(work2).Start(); } // just start the hread
    void work2() {
        Thread.Sleep(100); // do your work
        BeginInvoke(new Action(finish)); } // execute finish() on main thread
    

提交回复
热议问题