Метод блокировки потока пользовательского интерфейса - PullRequest
0 голосов
/ 08 июня 2018

Недавно я создал вспомогательный метод для регулирования скорости события изменения свойства, чтобы сохранить данные в моей локальной базе данных с заданной задержкой.Единственная проблема, с которой я столкнулся, заключается в том, что метод, по-видимому, не работает асинхронно и не блокирует мой поток пользовательского интерфейса.

Чтобы проверить это, я прикрепил событие в моем SettingsViewModel к PercentageSliderViewModel:

public class SettingsViewModel : BaseVM
{
    public PercentageSliderViewModel Activity { get; set; }

    [...]

    public SettingsViewModel() {
        Activity.PropertyChanged += CreateThrottledCallback(Save, 1000);
    }

    [...]

    public async Task Save()
    {
        // Save data
    }
}

Это мой вспомогательный метод:

public PropertyChangedEventHandler CreateThrottledCallback(
            Func<Task> callback, int throttle = 1000)
{
    bool throttling = false;
    bool callFinal = false;

    return async(s, e) =>
    {
        if (throttling)
        {
            callFinal = true;
            return;
        }

        throttling = true;

        await callback?.Invoke();

        await Task.Delay(throttle).ContinueWith(_ => throttling = false);

        if (callFinal)
        {
            await callback?.Invoke().ContinueWith(_ => callFinal = false);
        }
    };
}

Несмотря на то, что регулирование работает нормально, когда я перемещаю ползунок слева направо и происходит обратный вызов, он «зависает» длянебольшое количество времени.

Отладка показывает, что он выполняется в потоке пользовательского интерфейса.

Как можно запустить метод CreateThrottledCallback асинхронно, чтобы он тогда не блокировал мой основной поток?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Неясно, что на самом деле делает ваш метод Save и действительно ли это действительно асинхронный метод.Вы можете попытаться выполнить его в фоновом потоке в вашем методе CreateThrottledCallback:

if (callback != null)
    await Task.Run(() => callback.Invoke());
0 голосов
/ 08 июня 2018

Поскольку это не имеет ничего общего с пользовательским интерфейсом, вы можете использовать ConfigureAwait(false).Это позволит избежать захвата текущего контекста синхронизации, и задача будет выполняться в TaskScheduler.Default контексте пула потоков.

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