首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在UWP中Win 10 IOT线程死锁

在UWP中Win 10 IOT线程死锁
EN

Stack Overflow用户
提问于 2018-11-23 19:32:21
回答 1查看 208关注 0票数 0

我想做的是:-在第一页加载之前,同步(甚至异步)从USB驱动器加载设置。

我所做的:-在OnLaunched App.xaml.cs方法中,我调用了这个静态函数:

代码语言:javascript
复制
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);
}

正如您现在所看到的,它是异步空方法,所以我甚至不想以任何方式将它与UI线程同步。它应该开火然后做点什么。使用ConfigureAwait(false),我希望确保它永远不会试图返回上下文。最后,这些返回是我尝试过的其他东西的残余(我希望这样做更好,这是最原始的解决方案,但仍然无法工作)。

无论如何,这就是乐趣的开始:当我用Win 10在本地机器上调试应用程序时,一切都运行得很好。在Raspberry Pi 3上安装的Win 10 IOT (我今天从零开始安装它,最后一个版本)上,我得到了死死的线程。

但僵局并不是最奇怪的事情。最奇怪的是它出现的时候。

正如我所说,调用此方法如下所示:

代码语言:javascript
复制
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
        Configuration.Settings.LoadSettings();

在此之后,此方法中的所有内容都将正常进行,因此我导航到下面的第一页:

代码语言:javascript
复制
if (e.PrelaunchActivated == false)
{
    if (rootFrame.Content == null)
    {
        rootFrame.Navigate(typeof(LogScreen), e.Arguments);
    }

    Window.Current.Activate();
}

一切都还能用。用户需要编写他的代码,我检查这段代码在设置中是否可用,然后该用户可以按"OK“键移动到下一页。在LogScreenViewModel的某个地方,这个方法负责:

代码语言:javascript
复制
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")时会发生死锁。基本上现在UI线程冻结了。如果等待足够长的时间,我将在输出中看到捕获的异常,说明信使似乎占为己有(我现在无法显示屏幕,因为我无法访问那个Raspberry ),在超时之后,这个线程被杀死(大约30秒或更多)--在UI线程解锁和应用程序继续到MainPage之后。它不会发生在PC上-- MainPage立即出现,没有例外,没有死锁。

我试着在第一页上等待大约1分钟,以检查某些死锁异常是否会自动触发--但它不会。只有在我尝试继续到下一页时,它才会触发。

我还尝试了什么来代替这种“火与忘”的方法:

  • 使OnLaunched异步并等待LoadSettings返回任务-相同的事情发生在同一个地方,在PC上没有问题。
  • 使用:Window.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => await Configuration.Settings.LoadSettings(); ).AsTask().Wait(); --如果我记得正确的话,它就会立即陷入僵局,即使在ConfigureAwait(false)无处不在,但它也发生在PC上。
  • 允许LogScreen加载,使其OnNavigatedTo方法异步并等待LoadSettings -相同的死锁在同一位置
  • 允许LogScreen像第2点那样从那里加载和使用Dispatcher。在PC上,在到达Wait()之后,它也以同样的方式陷入僵局。
  • 通过用AsTask().GetAwaiter().GetResults()替换每个等待,试图迫使.GetResults完全同步。在电脑上效果很好..。当然还有树莓的僵局。

我遗漏了什么?我还能做什么呢?因为老实说,在我看来,Win 10 IOT .NET运行时被窃听了什么的。

EN

回答 1

Stack Overflow用户

发布于 2018-11-26 13:14:28

我想我解决了这个问题。一般来说,这段代码不是我的,在深入挖掘之后,我注意到在我之前有人试图在导航到MainPage时列出其他一些外部设备。它并不是真正的异步安全代码(可能有人不知道同步上下文),它只在Win 10上工作,因为它在桌面上寻找COM0设备,而我只有COM2,所以根本没有调用引起麻烦的方法。

我仍然不知道它与我的配置有多关联(因为它在某种程度上没有它的作用),但是在我修复了这个旧的不异步安全代码的问题之后,它开始像预期的那样运行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53452095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档