Оптимизировать получение скриншотов в сервисе Windows (C#) - PullRequest
0 голосов
/ 05 мая 2020

Я создаю приложение для периодического распознавания изображений на снимках экрана, используя C# и. NET Framework 4.8. Приложение работает как служба Windows 10 (S) и поэтому не может делать снимки экрана пользовательского сеанса.

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

Моя проблема: сделать снимок экрана в P, скопировать его в файл с отображением памяти в P, получить копирование в S и распаковка изображения в S - это просто недостаточно быстро . Я говорю о 1-2 секундах при каждом запуске, но мой сервис должен иметь снимок экрана примерно каждые 600 мс или даже быстрее. Ниже приведены фрагменты кода.

Что бы вы предложили, чтобы ускорить рабочий процесс? Раньше я пробовал реальные файлы на диске, что было еще медленнее. Моя идея состояла бы в том, чтобы передать контекст устройства от P к S, но меня беспокоит его стабильность. В конце дня мне нужно изображение как EmguCV Mat в сервисе. В настоящее время я сохраняю снимок экрана в MMF как PNG для экономии памяти, но это не очень помогает.

Мой код для получения снимка экрана в процессе выглядит так:

private static readonly object memoryLock = new object();
public void TakeScreenshots(ref MemoryMappedViewStream screenshotMemoryStream)
{
    lock (memoryLock)
    {
        using (var screenCaptureBitmap = new Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height, PixelFormat.Format32bppArgb))
        using (var captureWrapper = Graphics.FromImage(screenCaptureBitmap))
        {
            screenshotMemoryStream.Position = 0;
            captureWrapper.CopyFromScreen(SystemInformation.VirtualScreen.Left, SystemInformation.VirtualScreen.Top, 0, 0, SystemInformation.VirtualScreen.Size);
            screenCaptureBitmap.Save(screenshotMemoryStream, ImageFormat.Png);
            screenshotMemoryStream.Flush();
        }
    }
}

Получение его на другом конце с использованием

screenshotMemoryStream.Position = 0;
var screenshot = new Bitmap(screenshotMemoryStream).ToImage<Rgba, byte>();

Я проверяю, все ли утилизировано правильно, поэтому не обращайте внимания на мою обработку потоков памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...