簡體   English   中英

在.net中,是否為進程中的每個System.Thread.Timer對象創建一個新線程?

[英]In .net does a new thread get created for each System.Thread.Timer object in a process?

我想以不同的時間間隔執行方法,並且正在考慮使用Timer類來安排此時間。 但是,我想了解一下Timer是否為每個新計划啟動了一個新線程,這可能會影響應用程序的性能。

對於System.Threading.Timer

簡短答案:90%的時間:否。 它使用線程池獲取現有線程(不執行任何操作)。

長答案:可能! 如果池中的所有線程都忙,則操作系統將需要創建一個新線程並將其添加到池中,然后由計時器使用。

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

提供一種機制,用於以指定的時間間隔在線程池線程上執行方法。 這個類不能被繼承。

對於其他計時器類型:

  • System.Windows.Forms.Timer會觸發一個新的Win32窗口消息,該消息Form設置的時間間隔發送到Form 它不使用專用線程也不使用池線程,而是使用Win32的SetTimer函數。

  • 默認情況下, System.Timers.Timer也將使用池線程(就像System.Threading.Timer一樣),但是允許您執行線程同步。 請參閱https://docs.microsoft.com/zh-cn/dotnet/api/system.timers.timer?view=netframework-4.8

使用協程的單線程替代品:

我建議您改為使用await Task.Delay因為它不會導致使用新線程(請記住Task不是線程)-盡管如果您確實使用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 );
        }
    }
}

Dai在回答有關計時器和線程的問題方面做得很好。

我以為我會給你一種替代的方式來編寫代碼。 您應該使用Microsoft的Reactive Framework(aka Rx)-NuGet System.Reactiveusing System.Reactive.Linq;添加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來確保代碼在該線程上運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM