没有阻塞控制台输出的while循环

5

最近我一直在开发一些多线程控制台应用程序,想知道如何实现这一点。我使用以下代码来控制应用程序创建的线程数量:

foreach(string s in File.ReadAllLines("file.txt")){
    while (threads >= maxThreads) ;
    Thread t = new Thread(() => { 
        threads++;
        //thread code - make network request using 's'
        Console.WriteLine("TEST");
        threads--;
        Thread.CurrentThread.Abort();
    });
    t.start();
}

然而,由于while循环,所创建的Console.WriteLine方法被阻塞,直到下一个空闲线程可用才会显示出来。有什么方法可以防止此while循环阻止Console.WriteLine调用吗?编辑-反转while循环条件。

2
此外,如果可以避免的话,请勿从多个线程向控制台写入内容。控制台不支持多线程。您的线程最终会相互阻塞,等待控制台。 - Blorgbeard
请@Blorgbeard更新状态。 - rodit
1
嗯,也不要调用Thread.Abort,没有必要。只需让线程正常结束即可。 - Blorgbeard
我们仍然不知道问题出在哪里。线程似乎被阻塞了 - 这很可能不是因为 while 循环.. 你可以尝试在其中加入 Thread.Sleep(1) - Blorgbeard
感谢@Blorgbeard和其他人的评论和回复。明天我会尝试使用信号量和Thread.sleep。 - rodit
显示剩余9条评论
2个回答

6

更新

根据您的评论...

这行代码

while (threads >= maxThreads) ;

等待线程状态发生变化的方式并不好,因为这会导致CPU在while语句中旋转。相反,应该使用专门用于线程同步的机制,例如Semaphore

这里是一个示例,展示了如何使用SemaphoreSlim处理非常类似的情况。

class TheClub      // No door lists!
{
  static SemaphoreSlim _sem = new SemaphoreSlim (3);    // Capacity of 3

  static void Main()
  {
    for (int i = 1; i <= 5; i++) new Thread (Enter).Start (i);
  }

  static void Enter (object id)
  {
    Console.WriteLine (id + " wants to enter");
    _sem.Wait();
    Console.WriteLine (id + " is in!");           // Only three threads
    Thread.Sleep (1000 * (int) id);               // can be here at
    Console.WriteLine (id + " is leaving");       // a time.
    _sem.Release();
  }
}

谢谢回复,但这只是我的问题犯了一个错误。我觉得太蠢了 - 我会编辑问题! - rodit
1
@rodit 去掉分号。 - omerfarukdogan
即使进行了编辑,你的 while 循环仍然没有包括线程创建和 Console.WriteLine,因为在 while 后面有一个 ;,并且因为没有 {} 来包含 while 体中的多个语句。 - Eric J.
哦...好吧,既然是这样,那你有一个会让CPU过度负载的while语句。使用其他构造来指示主线程可以继续运行。 - Eric J.
没错。@rodit,你的 while 循环条件第一次就是正确的。 - Blorgbeard
显示剩余4条评论

4

使用while循环和thread.abort(或thread.suspend等)对CPU的消耗很大,而且不是线程同步的正确方式。尝试使用ManualResetEvent和AutoResetEvent,它们在线程同步方面非常有效,并且不会导致CPU占用率飙升。


信号量更合适。 - Eric J.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接