Мое приложение Xamarin.Forms содержит Slider, который при изменении вызывает обработку изображения на основе значения Slider. Обработка изображения - это интенсивная загрузка процессора, которая занимает около 200 мс. В результате чувствительность ползунка очень низкая.
Я переместил обработку изображения в отдельный поток, но отклик все еще медленный. Однако, когда я заменяю операцию на Thread.Sleep(200)
, отклик велик. Это заставляет меня поверить, что даже при запуске в отдельном потоке обработка изображений занимает все ресурсы ЦП, поскольку значение Slider может меняться гораздо чаще.
Вот мое текущее решение: когда Slider изменяется, добавьте обработку изображений Action
в список (но пока не выполняйте ее). Каждые 1000 мс берите последний Action
в списке и очищайте список. Выполните Action
в асинхронном режиме. Это предотвратило бы слишком много задач обработки изображений, занимающих все процессорное время. Вот упрощенная версия моего кода:
public class MainViewModel : ViewModelBase
{
private Timer timer;
private List<Action> actions;
public MainViewModel()
{
timer = new Timer(200);
timer.Elapsed += TimerElapsed;
timer.AutoReset = true;
timer.Enabled = true;
actions = new List<Action>();
}
// Processed image to be displayed
private SKBitmap image;
public SKBitmap Image
{
get => image;
set => Set(ref image, value);
}
// Slider value to be used in image processing
private double threshold;
public double Threshold
{
get => threshold;
set => Set(ref threshold, value);
}
// Command is called whenever the Slider value is changed
public ICommand SetThresholdCommand =>
new RelayCommand(() =>
{
actions.Add(() => ProcessImageAsync(Threshold));
});
private async void ProcessImageAsync(double threshold)
{
SKBitmap processedImage = null;
await Task.Run(() =>
{
processedImage = VisionService.ProcessImage(threshold);
}
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
Image = processedImage;
}
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
if (actions.Any())
{
actions.Last()(); // execute the last action added
actions.Clear(); // ignore all previous actions
}
}
}
Это решение работает, но наличие таймера кажется хакерским, и мне не нравится произвольное значение 1000 мс, которое не является оптимальным и, скорее всего, потребуется быть другим на других устройствах. Какие есть лучшие решения?