Я довольно новичок в 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 выполняется в рабочем потоке. Тем не менее мой пользовательский интерфейс блокирует.