Я работаю над приложением обновления прошивки и пытаюсь использовать Async / Await, чтобы избежать блокировки пользовательского интерфейса. Проблема, с которой я сталкиваюсь, состоит в том, что процесс обновления прошивки требует последовательности шагов, которые должны выполняться последовательно (что не является асинхронным). Тем не менее, похоже, что asyn c - это еще и путь к go, когда используется пользовательский интерфейс, чтобы избежать зависания приложения. Так как же нам не блокировать пользовательский интерфейс, последовательно завершать длительный ряд задач, а не израсходовать или тратить потоки?
Вот пример, не являющийся асинхронным c, для иллюстрации проблемы:
public class FirmwareUpdateViewModel : ObservableObject
{
//ctor
public FirmwareUpdateViewModel()
{
// Process should start on page load
updateFirmware();
}
private void updateFirmware()
{
//...
DeviceHandshake();
SendMessage(Commands.RestartDevice);
GetFWFileData();
WaitForDevice(timeout);
SendMessage(PreliminaryData);
//...
}
}
Моя первая попытка была await Task.Run(() =>
всем:
public class FirmwareUpdateViewModel : ObservableObject
{
//ctor
public FirmwareUpdateViewModel()
{
updateFirmwareAsync();
}
private async void updateFirmwareAsync()
{
//...
await Task.Run(() => DeviceHandshakeAsync());
await Task.Run(() => SendMessageAsync(Commands.RestartDevice));
//...
}
}
Проблема здесь, кроме async void
, заключается в том, что из-за вирусной природы Asyn c, когда я жду внутри DeviceHandshakeAsync
, плюс, если Task.Run()
работает в своем собственном потоке, то мы теряем тонну потоков.
Затем я попытался сбросить Task.Run(() =>
и просто ждать каждого метода, но, насколько я знаю, под-методы вернутся, когда встретят внутренний await
, и начнут запускать следующий под-метод до завершения предыдущего. И теперь я пытаюсь запустить метод firmwareUpdate asyn c, но не ожидаю суб-методов в попытке сохранить их синхронность и бороться с вирусной природой, но это блокирует пользовательский интерфейс:
public class FirmwareUpdateViewModel : ObservableObject
{
//ctor
public FirmwareUpdateViewModel()
{
Result = new NotifyTaskComplete<bool>(updateFirmwareAsync());
}
private async Task<bool> updateFirmwareAsync()
{
//...
DeviceHandshake();
SendMessage(Commands.RestartDevice);
//...
}
}
Проблема здесь, очевидно, в том, что без await
s мы работаем синхронно и в потоке пользовательского интерфейса. Ничто еще не "щелкнуло" для меня в понимании правильного подхода здесь. Как мы это делаем правильно?
Редактировать: Я понял, что пропустил большую часть проблемы ... что USB обрабатывается сторонней библиотекой, которая работает синхронно. Поэтому мне нужно как-то обернуть эти функции, чтобы избежать блокировки пользовательского интерфейса:
public class FirmwareUpdateViewModel : ObservableObject
{
//ctor
public FirmwareUpdateViewModel()
{
// Don't block the UI with this
updateFirmware();
}
private void updateFirmware()
{
//...
// Run all non-blocking but sequentially
DeviceHandshake();
SendMessage(Commands.RestartDevice);
GetFWFileData();
WaitForDevice(timeout);
SendMessage(PreliminaryData);
//...
}
private void SendMessage(Command)
{
// Existing code, can't make async
USBLibrary.Write(Command);
}
}
Вот почему я так растерялся, потому что asyn c хочет распространяться, но я не могу между конструктором и конец библиотеки.