ReactiveCommand в приложении WPF / ReactiveUI блокирует поток пользовательского интерфейса - PullRequest
0 голосов
/ 29 октября 2019

Я довольно новичок в ReactiveUI и у меня странное поведение с ReactiveCommand.

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

У меня есть кнопка, которая связана с ReactiveCommand, и команда запускает запрос к базе данных. Пока запрос длится, я хочу показать какую-то анимацию.

Проблема в том, что, что бы я ни пытался, запрос блокирует мой поток пользовательского интерфейса.

Вот часть моего кода:

public ReactiveCommand<Unit, Unit> StartExportCommand { get; }

//The constructor of my view model
public ExportDataViewModel(IDataRepository dr)
{
    this.dr = dr;

    //...

    StartExportCommand = ReactiveCommand.CreateFromTask(() => StartExport());

    //...
}


private async Task StartExport()
{               
    try
    {                
        Status = "Querying data from database...";

        //Interestingly without this call the Status message would not even be shown!
        //The delay seems to give the system the opportunity to at least update the
        //label in the UI that is bound to "Status".
        await Task.Delay(100);

        //### This is the call that blocks the UI thread for several seconds ###
        var result = await dr.GetValues();

        //do something with result...

        Status = "Successfully completed";
    }
    catch(Exception ex)
    {
        Status = "Failed!";

        //do whatever else is necessary
    }
}

//This is the GetValues method of the implementation of the IDataRepository. 
//The dictionary maps measured values to measuring points but that should not matter here.
//ValuesDto is just some container for the values.
public Task<IDictionary<int, ValuesDto>> GetValues()
{            
    //...

    return Task<IDictionary<int, ValuesDto>>.Factory.StartNew(() =>
    {
        //### here is where the blocking calls to the database
        //### specific APIs take place

        return result;
    }, TaskCreationOptions.LongRunning);

}

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

Что-то не так с этим шаблоном, или я должен пойти другим путем? с наблюдаемыми?

Редактировать 1

Мне известно о том, что async! = потоки. Я думал, однако, что Task с TaskCreationOptions.LongRunning заставит код блокировки выполняться в потоке пула потоков.

Редактировать 2

В соответствии с рекомендацией Энди, которую я установилточка останова внутри моей задачи и заглянул в окно Debug Threads. Это говорит мне, что Task выполняется в рабочем потоке. Тем не менее мой пользовательский интерфейс блокирует.

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