【问题标题】:why my infinite loop doesn't work为什么我的无限循环不起作用
【发布时间】:2023-03-14 11:00:01
【问题描述】:

我在一个类中有一个静态方法:

public static void MakeThreadModified(string s)
{
    new Thread(() => 
    {
        Thread.CurrentThread.IsBackground = true; 
        /* run your code here */
        while (true)
        {
            Console.WriteLine(s);
            Thread.Sleep(500);
        }

    }).Start();
}

我在 Main() 中这样调用这个方法:

    string[] str = {"A", "B", "C", "D", "E"};
    foreach (var v in str)
    {
        MakeThreadModified(v);
    }

我惊讶地发现结果是:

A
E
C
B
D

但是为什么我会得到这个结果?我以为它会不停地在控制台上连续打印从“A”到“E”的字母,但它只是每次打印每个字母一次。那么为什么会这样呢?

【问题讨论】:

  • 您正在创建 5 个单独的线程,它们都进入睡眠状态。你在期待什么?当然,他们都会在睡觉前登录控制台
  • 在 Main 的末尾是否有一个 Console.ReadLine() 调用来阻止您的应用程序的主线程终止?如果没有,请添加它。
  • 我认为通过他的循环,他希望每个线程都能继续打印字母。
  • @apomene 为什么500毫秒后没有一个线程重新开始运行?
  • @Derek 是的,这就是我想做的。

标签: c# multithreading loops


【解决方案1】:

由于您已将线程.IsBackground 属性设置为true,因此该线程不会使您的应用程序保持活动状态。所以在你的MakeThreadModified-loop 结束后,程序结束,所以线程...... 在循环之后添加Console.ReadLine() 以保持应用程序处于活动状态...

【讨论】:

  • 另一种选择是等待已创建任务的列表。
  • @M.kazemAkhgary 那肯定是实现他的目标的更好方法:)
【解决方案2】:

另一种选择可能是加入所有线程以防止它们终止。

但使用任务可能更容易。

见:Create multiple threads and wait all of them to complete

【讨论】:

    【解决方案3】:

    尝试改用下面的代码。我怀疑你在 main 的末尾没有 Console.ReadLine()。

    class Program
    {
        static void Main( string[ ] args )
        {
            string[ ] str = { "A", "B", "C", "D", "E" };
            foreach( var v in str )
            {
                MakeThreadModified( v );
            }
            Console.ReadLine( );
        }
    
        public static void MakeThreadModified( string s )
        {
            new Thread( obj =>
            {
                Thread.CurrentThread.IsBackground = true;
                /* run your code here */
                while( true )
                {
                    Console.WriteLine( $"[{Thread.CurrentThread.ManagedThreadId}] {( string )obj}" );
                    Thread.Sleep( 500 );
                }
    
            } ).Start( s );
        }
    }
    

    【讨论】:

      【解决方案4】:

      好吧,我不是 C# 开发人员,但编程领域的一个普遍概念是,某些程序的 main() 在一个特定线程(主线程)中运行,并且以同样的方式,其他线程在它们的工作已经完成并且没有处于无限循环的情况下,主线程也完成了,无论任何其他线程并行运行。因此,当主线程结束时,您将不会收到来自任何其他线程的任何输出,因为程序主输出与主线程(调用程序时启动的那个)相关联。

      正如@Derek 之前所说,正确的做法是:在主线程终止之前“加入所有线程”。 join() 在调用时就像主线程的信号量,即:对于在特定线程上调用的每个 .join(),主函数必须等待该特定线程完成。 p>

      t1.Join();
      t2.Join();
      t3.Join();
      

      强制主线程等待 t1、t2 和 t3。这里的问题是您创建了匿名线程,因此没有简单的方法来引用它们。

      正如我之前所说:我不是 C# 开发人员,所以我真的不知道处理它的最佳方法是什么(也许通过线程池?),但是前面提到的添加 @ 的解决方案987654325@ 可能会解决问题,即使与其他线程完全无关,这只是让主线程等待某些东西(来自用户的输入)的“技巧”。

      我整篇文章的想法是警告你存在一个main thread,如果你没有明确通知它(通过.join()),它不会关心或知道其他并行运行的线程。

      【讨论】:

        猜你喜欢
        • 2021-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多