在.net中,是否为进程中的每个System.Thread.Timer对象创建一个新线程?

时间:2019-08-04 20:05:16

标签: c# .net multithreading

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

2 个答案:

答案 0 :(得分:4)

对于System.Threading.Timer

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

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

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

  

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

对于其他计时器类型:

使用协程的单线程替代品:

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

Task.Run

答案 1 :(得分:2)

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

我想我会给你一种替代的方式来编写代码。您应该使用Microsoft的Reactive Framework(又名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来确保代码在该线程上运行。