How do I tell when all threads in a pool are complete

I have an app that uses a thread pool to ping all hosts on the local network. Each thread updates a listview with the status of that IP - alive or dead. When all the threads are done, I want to remove all the dead links from the list view.

  1. How can I tell when all the threads have done their job
  2. What is the best way to loop over the listview backwards (I assume backwards is best since the items are indexed...), removing each dead link (text in column 1 = "dead")

Thanks in advance.



Answer this question

How do I tell when all threads in a pool are complete

  • Bill Byrnes

    Yarg.

    I created a new thread that does cleanup - the function looks like this:

    private void Cleanup(object key)

    {
    _ewh.WaitOne();
    for (int i = listView1.Items.Count - 1; i > -1; i--)
    {
    if (_InvokeGetListView(i, 1) == "Dead")
    _InvokeRemoveListItem(i);
    }
    }

    At the end of all of my other threads I do this check in the finally statement:

    finally

    {
    tc--;
    if (tc == 0 && ats)
    _ewh.Set();
    }

    I got the cross-threading error again, so I hacked those invoke functions. This sure would be a lot easier if I could run the cleanup from the main thread. As it is, the invoke function is returning an error - return type must be able to be converted to a string or something like that. I have no idea what to do about this because I don't understand the invoke/delegate thing.

    private delegate string _InvokeGetListViewDelegate(int _row, int _column);

    private string _InvokeGetListView(int _row, int _column)

    {

    // If it's coming from another thread, Invoke _InvokeToListView trough the _InvokeToListViewDelegate and end this thing.

    if (this.InvokeRequired) { this.Invoke(new _InvokeGetListViewDelegate(_InvokeGetListView), _row, _column); return; }

    // If it passed that last test, then it's either coming from the form's own thread or invoked from another thread, and the stuff can be edited safely.

    return listView1.Items[_row].SubItems[_column].Text;

    }

    private delegate void _InvokeRemoveListItemDelegate(int _row);

    private void _InvokeRemoveListItem(int _row)

    {

    // If it's coming from another thread, Invoke _InvokeToListView trough the _InvokeToListViewDelegate and end this thing.

    if (this.InvokeRequired) { this.Invoke(new _InvokeRemoveListItemDelegate(_InvokeRemoveListItem), _row); return; }

    // If it passed that last test, then it's either coming from the form's own thread or invoked from another thread, and the stuff can be edited safely.

    listView1.Items[_row].Remove();

    }


  • Oleg_Ivanov

    Slick.
  • TANWare

    Create an integer that stores how many threads are running.
    At the beginning of the threads that need to be counted, add 1 to this integer.
    At the end of those threads, remove 1, and if it's 0 after removing AND all threads have started (create a bool for this too, to flag that every needed thread is started), then all threads have done their work (and set the all-started bool to false).

    Backwards
    for (int i = listView1.Items.Count -1; i > -1; i--)
    {
    // listView1.Items[i].
    }


  • stupots

    nah, don't do while(bool){thread.sleep()} things.
    Put one of these in your code somewhere:
    System.Threading.EventWaitHandle _ewh = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset);


    The thread that needs to wait (don't do this on UI thread) till everything's done does this:
    _ewh.WaitOne();

    The last thread (the one where all threads started and the integer is 0) does:
    _ewh.Set();
    to let the waiting thread continue it's work.

    That's one of the clean ways to let a thread wait for another thread. :)


  • Romek

    if (this.InvokeRequired) { return this.Invoke(new _InvokeGetListViewDelegate(_InvokeGetListView), _row, _column); /* and remove return here (which returned something (null) to ignore the stuff below) */}

    i'm not sure if that really works, try playing around with the invoke thing a bit, cause you need to get the parameter trough the invoke that is done up there ;)

    but i don't think invoke is needed when just reading some text.



  • M. Leary

    Would it make the most sense to have that cleanup process run in the last thread then I thought it would be cleaner to have it run from the main thread so I wouldn't have to figure out that invoke/delegate nonsense for the delete :) can I create a do -while integer > 0 sleep function in the main thread, then perform the cleanup after it exits this loop Is there a more elegant way


  • How do I tell when all threads in a pool are complete