【问题标题】:C# Multithreading - Threads don't runC# 多线程 - 线程不运行
【发布时间】:2016-08-18 06:29:34
【问题描述】:

我正在从我通常的 C++ 编程中自学 C#,现在我正在做线程。

以下简单代码编译良好,应该通过线程在循环中输出哔哔声 30 秒。

using System;
using System.Runtime.InteropServices;
using System.Threading;

class BeepSample
{
    [DllImport("kernel32.dll", SetLastError=true)]
    static extern bool Beep(uint dwFreq, uint dwDuration);

    static void Main()
    {
        Console.WriteLine("Testing PC speaker...");
        for (uint i = 100; i <= 20000; i++)
        {
            var BeepThread = new Thread(delegate() { Beep(i, 30000); });            
        }

        Console.WriteLine("Testing complete.");
        Console.ReadLine();
    }
}

唯一的问题是线程似乎不起作用。

我知道我缺少一些基本的东西。

有什么想法吗?

【问题讨论】:

  • 只要你输入new Thread(),就结束了;您的项目已经有旧代码。 C# Cookbook 中的并发,@StephenCleary

标签: c# multithreading


【解决方案1】:

你忘了开始线程MSDN link

for (uint i = 100; i <= 20000; i++)
{
    var BeepThread = new Thread(delegate() { Beep(i, 30000); });
    BeepThread.Start();
}

但这看起来很可疑。为什么需要 19900 个线程?可能您希望有 1 个线程,该线程内部有一个循环并暂停一小段时间以通过蜂鸣器输出不同的频率。

【讨论】:

  • 您还应该保留对Thread 对象的引用,这样它们在完成之前就不会被GCed
【解决方案2】:

唯一的问题是线程似乎不起作用。

这方面从你没有启动线程让他们做任何事情的部分很清楚

代码还有很多其他问题:

  • 关闭问题,需要进一步修改

    for (uint i = 100; i <= 20000; i++)
    {
      int icopy = i;
      var BeepThread = new Thread(delegate() { Beep(icopy, 30000); });    
      BeepThread.Start();        
    }
    
  • Thread 类将启动 foreground threads 并且每个逻辑处理器内核都有能力一次处理一个线程,每个 Thread 对于 computation and memory 来说都是非常昂贵的资源,因为它需要分配Thread Environment Block, Kernel Stack Memory, User Stack Memory,当前代码即使运行了,也会杀死你的系统,而你大多必须杀死进程才能退出它

  • Console.ReadLine(); 只会阻塞Main Thread / Ui Thread,即使Main thread / Ui thread 退出且未被阻塞,其他处于前台的线程仍将继续,理想的阻塞方法是在每个线程对象上调用Join,这将要求主线程等待完成

  • 重写相同代码的首选方法之一是使用任务并行库:

     Parallel.For(100, 20000,
     , new ParallelOptions { MaxDegreeOfParallelism =  
    Environment.ProcessorCount } 
    i =>
    {
       int icopy = i;
        Beep(icopy, 30000);
    });
    

好处:

  • 代码不会创建这么多线程并杀死系统
  • thread pool (Background threads) 上工作,并且只使用调用所需的线程数,并且最大数量永远不会超过系统的 Processor count,并且大多数情况下要少得多,因为线程被重用,因为没有主要的长时间运行计算
  • 自动屏蔽Main thread / Ui Thread

【讨论】:

  • 最佳答案。比预期了解更多关于线程的知识。谢谢。
  • 也可以查看上面提到的这本书“Concurrency in C# Cookbook”,@StephenCleary,以更好地理解 C# 中的并发
  • 如果您发现它对您的用例有用,您可以接受答案
【解决方案3】:

好的,谢谢大家。去吃午饭了。

我实现了...

for (uint i = 500; i <= 550; i++)
    {
        uint icopy = i;
        var BeepThread = new Thread(delegate() { Beep(icopy, 30000); });
        BeepThread.Start(); 
    }

效果很好。

正如预测的那样,在主线程执行后线程并没有终止,但它做了我想要的,这太棒了。

祝福你们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2021-02-20
    • 2018-07-03
    • 2021-11-29
    相关资源
    最近更新 更多