Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程工作线程状态_C#_.net_Multithreading_Threadpool_Thread State - Fatal编程技术网

C# 多线程工作线程状态

C# 多线程工作线程状态,c#,.net,multithreading,threadpool,thread-state,C#,.net,Multithreading,Threadpool,Thread State,我创建我的线程作为 for (int i = 0; i < threadCount; i++) { Searcher src = new Searcher(i, this); threads[i] = new Thread(new ThreadStart(src.getIpRange)); threads[i].Name = string.Format(i.ToString()); } foreach (Thread t in threads)

我创建我的线程作为

 for (int i = 0; i < threadCount; i++)
 {
     Searcher src = new Searcher(i, this);

     threads[i] = new Thread(new ThreadStart(src.getIpRange));
     threads[i].Name = string.Format(i.ToString());
  }

  foreach (Thread t in threads)
  {
     t.Start();
  }
for(int i=0;i
使用threadCount(=100150255等),但我无法知道有多少线程在工作。在执行时间

我想控制所有线程何时完成任务。给我一个信息,比如“所有线程都已停止,作业已完成…”
像backgroundWorker的RunWorkerCompleted事件一样,为什么不能使用critical section protected单个变量来控制多个活动线程?线程函数可以修改这个变量(当然,已经进入临界区)。

确定所有线程何时完成很简单

for (int i = 0; i < threadCount; i++)
{
    threads[i].Join();
}

Console.WriteLine("All threads are done!");
for(int i=0;i

您可以详细说明其他要求吗?

您可以检查线程的
ThreadState
属性

使用异步方法可能更好。这将为您提供一个
WaitHandle
对象,您可以使用
WaitHandle.WaitAll
等待所有异步方法完成

下面介绍异步编程:
首先,我必须指出,创建100、150、255等线程可能不是一个好主意。您最好使用
线程池
任务
类(如果使用.NET 4.0)。除此之外,还有两种成熟的等待所有线程完成的方法

加入线程。

线程。连接
块,直到目标线程完成

for (int i = 0; i < threadCount; i++) 
{ 
   Searcher src = new Searcher(i, this); 
   threads[i] = new Thread(new ThreadStart(src.getIpRange)); 
   threads[i].Name = string.Format(i.ToString()); 
} 

foreach (Thread t in threads) 
{ 
   t.Start(); 
} 

foreach (Thread t in threads)
{
   t.Join(); 
}

您肯定希望使用
任务
类来完成此任务或更高级别的概念,如
Parallel.ForEach
。直接使用
线程
类是相当痛苦的

我最近比较了各种异步方法,按从最佳(
Task
)到最差(
Thread
)的顺序列出

下面是一个使用
任务
的示例,演示了您想要做的事情:

// Start all tasks
var threads = new Task[threadCount];
for (int i = 0; i < threadCount; i++) 
{ 
  Searcher src = new Searcher(i, this); 
  threads[i] = Task.Factory.StartNew(src.getIpRange);
}

// How many are running right now?
var runningCount = threads.Count(x => x.Status == TaskStatus.Running);

// Register a callback when they have all completed (this does not block)
Task.Factory.ContinueWhenAll(threads, MyCallback);
//启动所有任务
var threads=新任务[threadCount];
对于(int i=0;ix.Status==TaskStatus.Running);
//当回调全部完成时注册回调(这不会阻塞)
Task.Factory.continuewhell(线程,MyCallback);

向Searcher添加一个委托,并从主线程向其传递一个回调方法,每个线程完成后都将调用该方法。启动每个线程时,将其添加到由该线程的ManagedThreadId设置关键字的字典中。当每个线程完成时,回调将从字典中删除该线程,并检查计数是否为零

        Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>();            

           for (int i = 0; i < threadCount; i++)
            {
                Searcher src = new Searcher(i, this);
                src.Done = new SearcherDoneDelegate(ThreadDone);
                threads[i] = new Thread(new ThreadStart(src.getIpRange));
                threads[i].Name = string.Format(i.ToString());
            }

            foreach (Thread t in threads)
            {
                lock (activeThreads)
                {
                    activeThreads.Add(t.ManagedThreadId, t);
                }
                t.Start();
            }


        }
        public void ThreadDone(int threadIdArg)
        {
            lock (activeThreads)
            {
                activeThreads.Remove(threadIdArg);
                if (activeThreads.Count == 0)
                {
                    // all done
                }
            }
        }

        public delegate void SearcherDoneDelegate(int threadIdArg);
        public static object locker = new object();



        public class Searcher
        {
            public SearcherDoneDelegate Done { get; set; }
            public void getIpRange()
            {
                Done(Thread.CurrentThread.ManagedThreadId);
            }
        }
Dictionary-activeThreads=new Dictionary();
对于(int i=0;i

如果一次运行的线程数超过您想要的数量,请将它们放入队列中,并在旧线程完成时将其剥离(使用回调)。

我尝试过这一点,但阻止了进度。@Rapunzo-确实,这就是问题所在
Thread.Join
是一个阻塞调用-因此
Console.WriteLine
在所有线程完成之前不会执行。您可以在另一个线程上运行这段代码,并在您选择的任何通知机制上进行适当的同步。为了简单起见,我在这里使用了
Console.WriteLine
。您能解释一下异步方法吗?您可以使用BeginInvoke()调用您的方法,而不是直接调用它。我尝试使用System.Threading.Tasks添加;到我的项目,但得到一个错误:命名空间“System.Threading”(是否缺少程序集引用?)中不存在类型或命名空间名称“Tasks”。要使用
Task
类,您需要.NET 4.0或.NET 3.5.is countdownevent在.NET 3.5中定义?否,我更新了我的答案,加入了一个带有简单实现的链接。你能解释什么是“关键部分受保护的单变量”吗?这里有一些例子和定义:我很难想象有一个应用程序,其中255个相同的线程是最佳的。请记住,在任何给定时间可在系统范围内运行的最大线程数=目标硬件中独立CPU内核的数量。fwiw根据我的经验(WinXP SP2),在一个进程中大约120秒后线程创建失败。这是在一个测试应用程序中实现的,每个基于套接字的应用程序客户端有一个线程。我不可能以这种方式实现实际的生产代码。我正在开发一个网络应用程序,所以我的线程
        Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>();            

           for (int i = 0; i < threadCount; i++)
            {
                Searcher src = new Searcher(i, this);
                src.Done = new SearcherDoneDelegate(ThreadDone);
                threads[i] = new Thread(new ThreadStart(src.getIpRange));
                threads[i].Name = string.Format(i.ToString());
            }

            foreach (Thread t in threads)
            {
                lock (activeThreads)
                {
                    activeThreads.Add(t.ManagedThreadId, t);
                }
                t.Start();
            }


        }
        public void ThreadDone(int threadIdArg)
        {
            lock (activeThreads)
            {
                activeThreads.Remove(threadIdArg);
                if (activeThreads.Count == 0)
                {
                    // all done
                }
            }
        }

        public delegate void SearcherDoneDelegate(int threadIdArg);
        public static object locker = new object();



        public class Searcher
        {
            public SearcherDoneDelegate Done { get; set; }
            public void getIpRange()
            {
                Done(Thread.CurrentThread.ManagedThreadId);
            }
        }