2017-07-26 40 views
1

我有一个在Windows 10 Mobile上运行的,用c#编写的UWP应用程序。我遇到了一个需要成为Singleton并且使用Lazy模式初始化的类。下面是我如何做它(这是几乎每个人是怎么做的),当应用程序是从零开始,“正常”使用当应用程序被暂停时,Windows UWP如何处理我的Lazy初始化Singleton类?

public class WindowsUniversalScanners 
{ 
    private static readonly Lazy<WindowsUniversalScanners> lWindowsScanner = new Lazy<WindowsUniversalScanners>(() => new WindowsUniversalScanners()); 

    public static WindowsUniversalScanners Instance { get { return lWindowsScanner.Value; } } 

    public delegate void ScannerDataEventHandler(ScannerDataEventArgs se); 

    public event ScannerDataEventHandler onScanData; 

    public delegate void ScannerStatusEventHandler(ScannerStatusEventArgs se); 

    public event ScannerStatusEventHandler onScanStatus; 

    public delegate void ScannerInitializationStatus(ScannerInitEventArgs si); 

    public event ScannerInitializationStatus onScannerInit; 

    private WindowsUniversalScanners() 
    { 
     StartScanner(); 
    } 

,一切工作正常。但是,如果该应用程序被暂停(意味着您切换到另一个应用程序,按下Windows键等),然后又恢复,则此类中的事件不再引发。

我也可以在此类中的代码中放置断点,并且看到断点在挂起之前应该处于中断状态,但在挂起之后,断点不再触发(这最终是事件从不触发的原因)。

因此,我假设Windows在应用程序暂停时销毁了我的Singleton?请注意,这也不是时间的事情。我读到,当一个应用程序暂停x秒,操作系统需要释放资源时,它可以终止事情。然而,即使我暂停了一秒钟,这个问题仍然会发生。应用程序的其他大部分功能在恢复后仍然正常工作。

那么,有人可以确认什么操作系统做的单身时,应用程序暂停具体?我已经做了大量关于应用程序生命周期的MSDN文档的阅读,但没有解决这个特定的问题。

另外,确认实际上这个类是否为空的最好方法是什么?我可以检查Instance = null来验证吗?假设是这样,我想我只需要重新实例化它呢?

谢谢!

+0

这可能有助于https://docs.microsoft.com/en-us/windows/uwp/launch-resume/suspend-an-app如果没有人回答你的问题,但你制定出一个解决方案,你应该张贴在这里回答你的问题。 – hatchet

回答

1

事实证明,这不是被处置的类。我相信如果没有提及课程,它可能会在5到10秒后被GC处置。这将满足操作系统放置此类的条件,同时暂停此类以减少暂停应用程序的占用空间。然而,这不是我的情况,因为它是一个单身人士,我仍然在我的页面上提到它。

注意!在我的情况下,硬件是PointOfService命名空间中的条形码扫描器。但是,有理由认为,Windows.Devices或其他命名空间中的任何硬件项都可能会发生此问题。像NFC,GPS等。你应该警惕,从暂停状态恢复后,并检查下面的解决方案为您的应用程序:

所以,其他事情之一,OS将“清理”时被暂停是硬件资源。就我而言,我不得不使用命名空间条码扫描器:

using Windows.Devices.PointOfService; 

,你再要“索赔”扫描仪做这样的事情:

BarcodeScanner.ClaimScannerAsync(); 

但是,正如我了解到,操作系统可以将您的设备索赔处理的任何一点。还有一个需要注意的警告。如果你不喜欢这样的内部类或单身的,像我一样:

private BarcodeScanner scanner = null; 
public ClaimedBarcodeScanner ClaimedScanner { get; set; } = null; 

,然后在构造函数或其他初始化方法,您填充这些属性与BarcodeScanner和ClaimedBarcodeScanner对象,然后操作系统部署的连接硬件,你失去了“要求”对他们来说,你的对象不会是空再次但是,如果您尝试访问或使用它们,你会得到一个的ObjectDisposedException。这是关键,因为当您尝试在任何时候重新连接,特别是恢复之后,你不能只是测试,看看如果这些属性为null,因为他们不会。相反,你必须尝试在try/catch块使用它们,赶上的ObjectDisposedException,在这一点上,重新连接或收回你的硬件(或扫描仪在我的情况)。

所以,我所做的就是让应用程序恢复事件,然后在这种情况下,尽量使用对象,如果我捕捉到了异常,用它来重新像这样:

private WindowsUniversalScanners() 
{ 
    //Get our event for when the app resumes from suspended state 
    Application.Current.Resuming += App_Resuming; 
    StartScanner(); 
} 

private async void App_Resuming(object sender, object e) 
{ 
    try 
    { 
     //When the app resumes from suspended state, the ClaimedScanner object will be disposed but NOT null. This means the only 
     //way to trap this is try to access a property in the object and catch an ObjectDisposedException. 
     var scannerStatus = ClaimedScanner.IsEnabled; 
    } 
    catch (ObjectDisposedException oe) 
    { 
     //Now we know we are in a stuck state, we can try to heal from it. First we destroy scanner object and set it to null. 
     if (DestroyScanner()) 
     { 
      //Finally we re-start the scanner 
      await StartScanner(); 
     } 
    } 
} 

希望这有助于!

相关问题