C# Thread.Join()上需要帮助

C# Thread.Join()上需要帮助,c#,multithreading,c#-4.0,C#,Multithreading,C# 4.0,这是我的设想 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

这是我的设想

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?*** 
} 
private void Form1\u加载(对象发送方,事件参数e)
{
List ListOftTasks=GetListOftTasks()
foreach(任务中的任务)
{
DoSomeWork=新的DoSomeWork();
线程工作线程=新线程(work.CompleteTask());
workerThread.Start();
}
***如何确定是否所有线程都已完成任务?***
} 
我想到了使用CurrentThread.join()。但是当前线程将是form_load()。所以它不会起作用

关于如何确定所有线程是否完成任务的任何建议


提前感谢。

您可以使用
WaitHandle.WaitAll
等待多个句柄-


编辑-删除关于UI线程的注释-由于这是asp.net而不是winforms…

如果您使用的是.net 4.0,为什么不利用TPL:

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

另外,如果这是ASP.NET,您最好使用它。

编辑:好的,现在我们有了更多的信息,并且知道问题并不是关于用户界面,很简单:

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();
}
List listoftask=getlistoftask()
列表线程=新列表();
foreach(任务中的任务)
{
DoSomeWork=新的DoSomeWork(任务);
线程工作线程=新线程(work.CompleteTask);
workerThread.Start();
添加(workerThread);
}
//现在所有线程都已启动,请依次加入以等待
//让他们完成。不要在普通应用程序的UI线程中执行此操作。
foreach(线程中的线程)
{
thread.Join();
}
当然,使用TPL的
WaitForAll
是一个比这更好的主意-如果你可以使用它,就这样做。但是如果您使用的是普通线程,
Join
就可以了


编辑:我一直假设您正在编写一个基于Form1\u加载方法的Windows窗体应用程序。如果你能在问题中提供更多的上下文,那将是很有帮助的

嗯,你的线程不太可能在你启动它们之后立即全部完成。。。您不应该阻止UI线程等待它们完成,因为您的UI将挂起

相反,您应该在每个
DoSomeWork
任务完成后将其回调到UI中。
DoSomeWork
可能有一个事件,您可以向其中添加处理程序,或者您可以将完成处理程序委托传递给构造函数,或者它可能直接了解表单并可以调用自己-这取决于它真正在做什么

无论如何,当任务有效完成后,您可以使用
Control.BeginInvoke
发回UI线程。表单可以跟踪完成了多少任务,这样,当所有任务都完成时,如果它需要做一些事情,它就可以这样做

如果这没有帮助,请提供更多信息,说明在所有任务完成后您希望发生什么,以及这些任务正在执行什么。

void Main()
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
{ var spooler=新spooler(); 随机r=新随机(); 对于(int i=0;i<10;i++) { var-work=newdosomework{Delay=r.Next(1005000)}; 后台处理程序。添加(工作); } 假脱机程序轮询(100); Logger.Log(“完成”); } 静态类记录器 { 内部静态无效日志(字符串消息) { WriteLine({0}表示“+msg,Thread.CurrentThread.ManagedThreadId); } } 公共类假脱机程序 { 私有对象_lock=新对象(); 私有列表_workItems=新列表(); 公共无效添加(DoSomeWork) { _工作项。添加(工作); 动作whenDone=()=>{lock(_lock)work.Done=true;}; (新线程(()=>work.CompleteTask(whenDone)).Start(); } 公众投票(整数率) { while(true) { var q=从c输入_工作项 其中c.Done==false 选择c; Logger.Log(“poll”); 整数计数=-1; 锁 { 如果(q.FirstOrDefault()==null)中断; count=q.count(); } Logger.Log(count+“to go”); 睡眠(速率); } } } 公共类档案室 { 公共布尔完成=错误; 公共整数延迟{get;set;} 公共作废完成任务(完成时的操作) { Logger.Log(“开始”+延迟); 睡眠(延迟); Logger.Log(“结束”); whenDone(); } } 15说开始2707 21开始2809 12.开始4586 27说开始4822 28说开始242 29说开始2989 从1374开始 31说开始4265 32说开始2679 33说开始4041 14日,民意测验说 14点10分 14日,民意测验说 14点10分 14日,民意测验说 14点10分 28表示结束 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 14日,民意测验说 14说9走 30表示结束 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 14日,民意测验说 14说8去 32表示结束 14日,民意测验说 14说7走 15表示结束 14日,民意测验说 14说6走 21表示结束 14日,民意测验说 14点5分 29日结束 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 14日,民意测验说 14点4分 33表示结束 14日,民意测验说 14说3去 14日,民意测验说 14说3去 31表示结束 14日,民意测验说 14点2分 14日,民意测验说 14点2分 14日,民意测验说 14点2分 12表示结束 14日,民意测验说 14说1走 14