【问题标题】:In .net does a new thread get created for each System.Thread.Timer object in a process?在 .net 中,是否为进程中的每个 System.Thread.Timer 对象创建了一个新线程?
【发布时间】:2019-08-04 20:05:16
【问题描述】:

我想以不同的时间间隔执行方法,并且正在考虑使用 Timer 类来安排这个。但是,我想了解 Timer 是否为每个新计划启动了一个新线程,这可能会影响应用程序的性能

【问题讨论】:

    标签: c# .net multithreading


    【解决方案1】:

    对于System.Threading.Timer

    简短回答:90% 的时间:没有。它使用线程池来获取现有线程(不做任何事情)。

    长答案:可能!如果池中的所有线程都忙,则操作系统将需要创建一个新线程并将其添加到池中,然后由 Timer 使用。

    https://docs.microsoft.com/en-us/dotnet/api/system.threading.timer?view=netframework-4.8

    提供一种机制,用于以指定的时间间隔在线程池线程上执行方法。这个类不能被继承。

    对于其他计时器类型:

    使用协程的单线程替代方案:

    我建议您改用await Task.Delay - 因为它不会导致使用新线程(请记住Tasks 不是线程) - 尽管如果您确实使用Task.Run 来运行协程在池线程中然后它可以在新线程上运行:

    public static class Foo
    {
        public static async Task<Int32> Main( String[] args )
        {
            Task loop30 = this.Every30Seconds();
            Task loop20 = this.Every20Seconds();
            Taks loop10 = this.Every10Seconds();
    
            await Task.WhenAll( loop30, loop20, loop10 );
    
            return 0;
        }
    
        public static async Task Every30Seconds()
        {
            while( true )
            {
                Console.WriteLine("Ping!");
    
                await Task.Delay( 30 * 1000 );
            }
        }
    
        public static async Task Every20Seconds()
        {
            while( true )
            {
                Console.WriteLine("Pong!");
    
                await Task.Delay( 20 * 1000 );
            }
        }
    
        public static async Task Every10Seconds()
        {
            while( true )
            {
                Console.WriteLine("Pang!");
    
                await Task.Delay( 10 * 1000 );
            }
        }
    }
    

    【讨论】:

    • 当它是来自 System.Threading 命名空间的计时器时,你是对的。但是.Net 中还有其他 3 个计时器。所以,如果你能写出完整的答案,那就太好了。
    【解决方案2】:

    Dai 很好地回答了有关计时器和线程的问题。

    我想我会给你另一种编写代码的方法。您应该使用 Microsoft 的反应式框架(又名 Rx)- NuGet System.Reactive 并添加 using System.Reactive.Linq; - 然后您可以这样做:

    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    
    EventLoopScheduler els = new EventLoopScheduler();
    
    els.Schedule(() => Console.WriteLine(Thread.CurrentThread.ManagedThreadId));
    
    IObservable<string> pings = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(30), els).Select(x => "Ping!");
    IObservable<string> pongs = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(20), els).Select(x => "Pong!");
    IObservable<string> pangs = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(10), els).Select(x => "Pang!");
    
    IObservable<string> query = Observable.Merge(els, pings, pongs, pangs);
    
    IDisposable subscription = query.Subscribe(x => Console.WriteLine($"{x} ({Thread.CurrentThread.ManagedThreadId})"));
    
    Console.ReadLine();
    
    subscription.Dispose();
    els.Dispose();
    

    EventLoopScheduler 创建一个单独的、专用的、可重复使用的线程,您可以一直使用该线程,直到您在其上调用 .Dispose()

    Observable.TimerObservable.Merge 都允许您指定要使用EventLoopScheduler 来确保代码在该线程上运行。

    【讨论】:

      猜你喜欢
      • 2020-04-04
      • 2013-09-23
      • 1970-01-01
      • 1970-01-01
      • 2014-12-10
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 2012-07-02
      相关资源
      最近更新 更多