Как я могу постоянно делать снимки экрана, не убивая производительность? - PullRequest
2 голосов
/ 15 сентября 2011

Требование таково:

Я должен выполнить команду, запрашивающую снимок экрана.Твист?Команда указывает время - и это время в прошлом.Не навсегда, заметьте, всего за 30 секунд.

Моя команда указывает текущую секунду, и соответствующий снимок экрана извлекается из скользящего кэша и сохраняется в постоянном месте для другого процесса.

Для этого я должен снимать скриншот каждую секунду и сохранять их в течение 30 секунд.После этого кеш может очиститься сам.

У меня вопрос

Какой метод для скриншотов наименее эффективен для рабочего стола?

Ответы [ 2 ]

6 голосов
/ 15 сентября 2011

Я не могу себе представить, что один кадр в секунду будет ужасен для производительности.Вы пробовали самый простой из возможных методов, чтобы увидеть, влияет ли это на производительность?

Посмотрите на http://www.dotnetjalps.com/2007/06/how-to-take-screenshot-in-c.html для получения информации о том, как сделать снимок экрана.используйте таймер:

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

Вам потребуется некоторая синхронизация в вашем кеше, чтобы предотвратить проблемы с многопоточностью (т.е. попытаться прочитать первый элемент в кеше, пока он выталкивается).Возможно, проще всего использовать блокировку, поскольку она не будет особенно чувствительной к производительности.

Что касается того, что использовать для кэша, я бы предложил LinkedList.Легко добавить в список (AddLast()) и удалить первый элемент (RemoveFirst()), и так как у вас будет только 30 из них, и запросы на снимки экрана будут относительно редкими, последовательное сканирование для получения n-гоэлемент не будет занимать слишком много времени.

Или вы можете реализовать простой циклический буфер, используя List или Array.Увеличьте индекс, чтобы он был местом вставки, оборачиваясь, когда вы увеличиваете с конца.Поиск тогда становится простым делом арифметики по модулю.

1 голос
/ 15 сентября 2011

В соответствии с тем, что сказал Джим, вы можете сохранить свой рабочий набор снимков экрана в ConcurrentDictionary<DateTime, Bitmap> и иметь два таймера: первый таймер добавит ваш скриншот в словарь, а второй удалит все, что старше 30 секунд из словаря.

Тем не менее, это будет ужасно для производительности в любом случае, если вы нарежете его.

Что-то вроде этого:

        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();
...