Помощь нужна на Thread.Join () - PullRequest
2 голосов
/ 12 апреля 2011

Вот мой сценарий.

private void Form1_Load(object sender, EventArgs e)
{
   List<tasks> listOfTasks =  GetListOfTasks()

   foreach(Task task in Tasks)
   {
      DoSomeWork work = new DoSomeWork();

      Thread workerThread = new Thread(work.CompleteTask());

      workerThread.Start();
   }

   ***How to determine if all threads have finished the task?*** 
} 

Я думал об использовании CurrentThread.join (). Но текущий поток будет form_load (). Так что не получится.

Любые предложения о том, как определить, все ли потоки завершили свою задачу.

Заранее спасибо.

Ответы [ 4 ]

3 голосов
/ 12 апреля 2011

Если вы используете .NET 4.0, почему бы не воспользоваться преимуществами TPL:

Task.WaitAll(
    listOfTasks.Select(
        item => Task.Factory.StartNew(() => 
        {
            DoSomeWork work = new DoSomeWork();
            work.CompleteTask();
        })
    ).ToArray()
);

Также, если это ASP.NET, вам лучше использовать асинхронные страницы .

3 голосов
/ 12 апреля 2011

РЕДАКТИРОВАТЬ: Хорошо, теперь у нас есть больше информации и мы знаем, что вопрос не действительно о пользовательском интерфейсе, это просто:

List<Task> listOfTasks =  GetListOfTasks()

List<Thread> threads = new List<Thread>();
foreach(Task task in Tasks)
{
   DoSomeWork work = new DoSomeWork(task);

   Thread workerThread = new Thread(work.CompleteTask);
   workerThread.Start();
   threads.Add(workerThread);
}

// Now all the threads have started, Join on them in turn to wait
// for them to finish. DON'T DO THIS IN A UI THREAD IN A NORMAL APP.
foreach (Thread thread in threads)
{
    thread.Join();
}

Конечно, использование TPL WaitForAll является лучшей идеей, чем эта - если вы можете ее использовать, сделайте это. Но если вы используете простые потоки, Join хорошо.


РЕДАКТИРОВАТЬ: я предполагаю, что вы пишете приложение Windows Forms, основанное на методе Form1_Load. Было бы полезно, если бы вы могли дать больше контекста в вопросе.

Что ж, ваши потоки вряд ли будут завершены сразу же после того, как вы их запустили ... и вам не следует блокировать поток пользовательского интерфейса , ожидающий их завершения, поскольку ваш пользовательский интерфейс зависнет .

Вместо этого вы должны сделать каждый вызов задачи DoSomeWork обратно в пользовательский интерфейс после его завершения. Либо DoSomeWork может иметь событие, к которому вы можете добавить обработчик, либо вы можете передать делегат обработчика завершения в конструктор, или, возможно, он знает о форме напрямую и может сам отозвать ее - это зависит от того, что он делает на самом деле.

В любом случае, когда задача успешно завершена, вы можете отправить сообщение обратно в поток пользовательского интерфейса, используя Control.BeginInvoke. Форма может отслеживать количество выполненных задач, поэтому, если ей нужно что-то сделать, когда все завершено, она может сделать это.

Если это не поможет, пожалуйста, дайте больше информации о том, что вы хотите сделать, когда все задачи завершены, и что эти задачи делают.

0 голосов
/ 12 апреля 2011
void Main()
{
    var spooler = new Spooler();
    Random r = new Random();
    for (int i = 0; i < 10; i++)
    {
        var work = new DoSomeWork { Delay = r.Next(100, 5000) };
        spooler.Add(work);
    }
    spooler.Poll(100);
    Logger.Log("finish");
}
static class Logger
{
    internal static void Log(string msg)
    {
        Console.WriteLine("{0} says " + msg, Thread.CurrentThread.ManagedThreadId);
    }
}
public class Spooler
{
    private object _lock = new object();
    private List<DoSomeWork> _workItems = new List<DoSomeWork>();
    public void Add(DoSomeWork work)
    {
        _workItems.Add(work);
        Action whenDone = () => { lock(_lock) work.Done = true; };
        (new Thread(()=>work.CompleteTask(whenDone))).Start();        
    }
    public void Poll(int rate)
    {
        while(true)
        {
            var q = from c in _workItems
                    where c.Done == false
                    select c;
            Logger.Log("poll");
            int count = -1;
            lock(_lock)
            {       
                if(q.FirstOrDefault() == null) break;
                count = q.Count();
            }
            Logger.Log(count + " to go");
            Thread.Sleep(rate);
        }
    }
}
public class DoSomeWork
{
    public bool Done = false;
    public int Delay { get; set; }
    public void CompleteTask(Action whenDone)
    {
        Logger.Log("begin " + Delay);
        Thread.Sleep(Delay);
        Logger.Log("end");
        whenDone();
    }
}

15 says begin 2707
21 says begin 2809
12 says begin 4586
27 says begin 4822
28 says begin 242
29 says begin 2989
30 says begin 1374
31 says begin 4265
32 says begin 2679
33 says begin 4041
14 says poll
14 says 10 to go
14 says poll
14 says 10 to go
14 says poll
14 says 10 to go
28 says end
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
14 says poll
14 says 9 to go
30 says end
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
14 says poll
14 says 8 to go
32 says end
14 says poll
14 says 7 to go
15 says end
14 says poll
14 says 6 to go
21 says end
14 says poll
14 says 5 to go
29 says end
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
14 says poll
14 says 4 to go
33 says end
14 says poll
14 says 3 to go
14 says poll
14 says 3 to go
31 says end
14 says poll
14 says 2 to go
14 says poll
14 says 2 to go
14 says poll
14 says 2 to go
12 says end
14 says poll
14 says 1 to go
14 says poll
14 says 1 to go
14 says poll
14 says 1 to go
27 says end
14 says poll
14 says finish
0 голосов
/ 12 апреля 2011

Вы можете использовать WaitHandle.WaitAll для ожидания нескольких дескрипторов - http://msdn.microsoft.com/en-us/library/z6w25xa6.aspx

Редактировать - удален комментарий о потоке пользовательского интерфейса - поскольку это asp.net, а не winforms ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...