Win 10 IOT блокировка потока в UWP - PullRequest
0 голосов
/ 23 ноября 2018

Что я хочу сделать: - синхронно (или даже асинхронно) загрузить настройки с USB-накопителя до загрузки первой страницы

Что я сделал: - в методе OnLaunched для App.xaml.cs я вызвал эту статическую функцию:

public static async void LoadSettings(string folderName = "Config", string fileName = "Settings.xml")
{
    try
    {
    StorageFile configFile = null;
    // scan through all devices
    foreach (var device in await KnownFolders.RemovableDevices.GetFoldersAsync().AsTask().ConfigureAwait(false))
    {
        // folder that should have configuration
        var configFolder = await device.GetFolderAsync(folderName).AsTask().ConfigureAwait(false);

        if (configFile != null && configFolder != null && await configFolder.GetFileAsync(fileName).AsTask().ConfigureAwait(false) != null)
        {
            throw new Exception("More than one configuration file detected. First found configuration file will be used.");
        }
        else
            configFile = await configFolder.GetFileAsync(fileName).AsTask().ConfigureAwait(false);
    }

    if (configFile == null)
        throw new Exception("Configuration file was not found, please insert device with proper configuration path.");

    string settingString = await FileIO.ReadTextAsync(configFile).AsTask().ConfigureAwait(false);

    XmlSerializer serializer = new XmlSerializer(typeof(Settings));
    using (TextReader reader = new StringReader(settingString))
    {
        AppSettings = (Settings)serializer.Deserialize(reader); // store settings in some static variable
    }
}
catch (Exception e)
{

    //return await Task.FromResult<string>(e.Message);
}

//return await Task.FromResult<string>(null);
}

Как вы можете видеть прямо сейчас, это асинхронный метод void, поэтому я даже не хочу синхронизировать его каким-либо образом с потоком пользовательского интерфейса.Надо просто стрелять и что-то делать.С ConfigureAwait (false) я хочу быть уверен, что он никогда не будет пытаться вернуться в контекст.Эти возвращения в конце являются остатками других вещей, которые я пробовал (я хотел сделать это лучше, это самое примитивное решение, и оно все еще не работает).

В любом случае, потому что здесь начинается самое интересное: все работает хорошо, когда я отлаживаю приложение на локальной машине с Win 10. И я получаю тупик на Win 10 IOT, установленном на Raspberry Pi 3 (я установил его с нуля, последняя версия).

Но тупикэто не самая странная вещь.Самое странное, когда он появляется.

Как я уже сказал, вызов этого метода выглядит следующим образом:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
        Configuration.Settings.LoadSettings();

После этого все в этом методе идет нормально, поэтому я перехожу на свою первую страницугде-то ниже:

if (e.PrelaunchActivated == false)
{
    if (rootFrame.Content == null)
    {
        rootFrame.Navigate(typeof(LogScreen), e.Arguments);
    }

    Window.Current.Activate();
}

Все еще работает.Пользователь должен написать свой код, я проверяю, доступен ли этот код в настройках, и после этого пользователь может нажать «ОК», чтобы перейти на следующую страницу.Где-то в LogScreenViewModel этот метод отвечает за это:

private void GoForward(bool isValid)
{
    try
    {
        _navigationService.NavigateTo("MainPage"); // it's SimpleIoc navigation from MVVMLight
    }
    catch (Exception e)
    {
        Debug.WriteLine($"ERROR: {e.Message}");
    }
}

И возникает тупик, когда достигается _navigationService.NavigateTo ("MainPage").В основном прямо сейчас поток пользовательского интерфейса зависает.Если я подожду достаточно долго, я увижу перехваченное исключение в Output, говорящее о том, что мессенджер казался занятым (я не могу показать экран, потому что у меня нет доступа к этой Raspberry прямо сейчас), и через некоторое время этот поток был убит (например, 30секунд или что-то) - после этого поток пользовательского интерфейса разблокируется, и приложение переходит на MainPage.Это не происходит на ПК - MainPage появляется немедленно, без исключений, без взаимоблокировок.

Я пытался ждать на первой странице около 1 минуты, чтобы проверить, не сработает ли какое-либо исключение взаимоблокировки самостоятельно, но это не так.т.Он будет срабатывать ТОЛЬКО после того, как я попытаюсь перейти на следующую страницу.

Что еще я пробовал вместо этого подхода «забыл и забыл»:

  • Выполнение асинхронного включения OnLaunched и ожидание возврата LoadSettings Task Task- то же самое происходит в одном и том же месте, и никаких проблем на ПК.
  • Использование: Window.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => await Configuration.Settings.LoadSettings(); ).AsTask().Wait(); Если я правильно помню, он сразу же блокируется в Wait (), даже с ConfigureAwait (false) везде, но это также произошлона ПК.
  • Позволяет LogScreen загружаться, делает его метод OnNavigatedTo асинхронным и ожидает LoadSettings - тот же тупик в том же месте
  • Позволяет LogScreen загружать и использовать Диспетчер оттуда, как в пункте 2. Он заблокировантаким же образом после достижения Wait (), на ПК тоже.
  • Попытка заставить LoadSettings быть полностью синхронными путем замены каждого await на AsTask (). GetAwaiter (). GetResults ().Он хорошо работал на ПК ... и, конечно, тупик на Raspberry.

Чего мне не хватает?Что еще я могу попробовать?Потому что, честно говоря, сейчас мне кажется, что среда выполнения Win 10 IOT .NET содержит ошибки или что-то в этом роде.

1 Ответ

0 голосов
/ 26 ноября 2018

Я думаю, что решил проблему.Этот код, вообще говоря, не мой, и после некоторого копания я заметил, что кто-то передо мной пытался перечислить некоторые другие внешние устройства при переходе на MainPage.Это был не совсем асинхронный код (кто-то, вероятно, не знал о контексте синхронизации), и он работал на Win 10 только потому, что на настольном компьютере он искал устройство COM0, а у меня только COM2, поэтому метод, вызывающий проблему, даже не вызывалсявсе.

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

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