简体   繁体   English

如何在不影响性能的情况下不断拍摄屏幕快照?

[英]How can I constantly take screen shots without killing performance?

The requirement is like this: 要求是这样的:

I must issue a command requesting a screenshot. 我必须发出命令以要求屏幕截图。 The twist? 扭曲? The command specifies a time - and that time is in the PAST. 该命令指定一个时间-该时间位于PAST中。 Not forever, mind you, just within a 30 second window. 在30秒的窗口内,永远不要紧紧提醒您。

My command indicates the actual second, and the corresponding screenshot is pulled from the rolling cache and saved in a permanent location for another process. 我的命令指示实际的秒数,并且相应的屏幕快照从滚动缓存中提取并保存在永久位置以供另一个进程使用。

To accomplish this, I must take a screenshot every second, and I must preserve them for 30 seconds. 为此,我必须每秒截图一次,并且必须将其保存30秒。 After that the cache can purge itself. 之后,缓存可以清除自身。

My question is 我的问题是

What method for screenshots is least impactful against the desktop? 哪种屏幕截图方法对桌面的影响最小?

I can't imagine that one frame per second is going to be terrible for performance. 我无法想象每秒一帧的性能会很糟糕。 Have you tried the simplest possible method to see if it impacts performance? 您是否尝试过最简单的方法来查看它是否影响性能?

Take a look at http://www.dotnetjalps.com/2007/06/how-to-take-screenshot-in-c.html for information on how to get a screen shot. 请查看http://www.dotnetjalps.com/2007/06/how-to-take-screenshot-in-c.html,以获取有关如何获取屏幕快照的信息。

I would suggest you use a timer: 我建议您使用计时器:

var ssTimer = new System.Threading.Timer((s) =>
    {
      GetAndStoreScreenShot();
    }, null, 1000, 1000);

You'll need some synchronization on your cache to prevent threading problems (ie trying to read the first item in the cache while it's being pushed out). 您需要在缓存上进行一些同步,以防止出现线程问题(即,在推出缓存时尝试读取缓存中的第一项)。 Probably easiest to use a lock, since that's not going to be particularly performance sensitive. 可能最容易使用锁,因为这对性能不是特别敏感。

As for what to use for a cache, I'd suggest a LinkedList . 至于用于缓存的内容,我建议使用LinkedList It's easy to append to the list ( AddLast() ) and remove the first item ( RemoveFirst() ), and since you'll only have 30 of them and requests for screen shots will be relatively infrequent, a sequential scan to get the nth item wouldn't be too time consuming. 将其追加到列表( AddLast() )并删除第一项( RemoveFirst() )很容易,由于您只有30个,并且屏幕截图的请求相对较少,因此顺序扫描以获取第n个项目不会太耗时。

Or you can implement a simple circular buffer using List or Array . 或者,您可以使用ListArray实现一个简单的循环缓冲区。 Increment an index to be the insertion spot, wrapping around when you increment off the end. 递增一个索引作为插入点,当递增到末尾时会回绕。 A lookup then becomes a simple matter of modulo arithmetic. 然后查找就变成了简单的模运算问题。

Along the lines of what Jim said, you could store your working set of screenshots in a ConcurrentDictionary<DateTime, Bitmap> , and have two timers: The first timer would add your screenshot to the dictionary, and the second would remove anything older than 30 seconds from the dictionary. 按照吉姆所说的,您可以将屏幕快照的工作集存储在ConcurrentDictionary<DateTime, Bitmap> ,并具有两个计时器:第一个计时器会将您的屏幕截图添加到字典中,第二个计时器将删除30年前的任何内容字典中的秒数。

However, this is going to be terrible for performance pretty much any way you slice it. 但是,这几乎会对您进行切片的任何方式的性能都造成严重影响。

Something along these lines: 这些方面的东西:

        var imageDictionary = new ConcurrentDictionary<DateTime, Bitmap>();

        var screenshotTaker = new System.Timers.Timer(1000);
        screenshotTaker.Elapsed += (sender, e) =>
                                       {
                                           Bitmap bmp = GetScreenshot();
                                           imageDictionary.TryAdd(DateTime.Now, bmp);
                                       };

        var screenshotRemover = new System.Timers.Timer(1000);
        screenshotRemover.Elapsed += (sender, e) =>
                                         {
                                             RemoveExpiredBitmaps();
                                         };

        screenshotTaker.Start();
        screenshotRemover.Start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM