我在 Xamarin.Forms 中對應用程式單例使用延遲初始化(應用程式在 iOS 上運行):
public sealed class DataSingleton
{
private static readonly Lazy<DataSingleton> lazy = new Lazy<DataSingleton>(() => new DataSingleton(), LazyThreadSafetyMode.PublicationOnly); // tried withou 2nd parameter as well
public static DataSingleton Instance
{
get { return lazy.Value; }
}
...
}
我在 webserver 中呼叫它,它運行為 Angular 中的前端提供資料(使用 web 視圖顯示 Angular 代碼)
var server = new WebServer(o => o
.WithUrlPrefix($"http://localhost:{appSettings.ApiPort}")
.WithMode(HttpListenerMode.EmbedIO))
.WithCors()
.WithLocalSessionManager()
.WithWebApi("/api", m => m
.WithController<TestController>()
.WithController<SettingsController>()
.WithController<ReportController>()
.WithController<SystemController>())
.WithModule(new ActionModule("/", HttpVerbs.Any,
ctx => ctx.SendDataAsync(new { Message = "Error" })))
.RunAsync();
在控制器中稱為 DataSingleton 來獲取/設定資料,但在應用程式從后臺回傳后,DataSingleton.Instance為空。
當應用程式在后臺短時間(大約 5 分鐘)時,我應該怎么做才能不丟失單例資料
更新 - 我發現這個問題只存在于控制器中,因為當應用程式回到前面時,我可以看到 AppDelegate
WillEnterForeground事件中的所有資料..
uj5u.com熱心網友回復:
鑒于是網路服務器出現問題,請在應用程式進入后臺時停止它。當應用程式回傳時再次啟動它(或根據需要延遲啟動)。
代碼可能是這樣的:
應用程式.xaml.cs:
public static Webserver MyWebServer
{
get
{
if (_server == null)
{
_server = new Webserver(...);
}
return _server;
}
}
public static void StopWebServer()
{
if (_server != null)
{
_server.Dispose();
// So will be created again, on next reference to MyWebServer.
_server = null;
}
}
private static Webserver _server;
...
protected override void OnSleep()
{
StopWebServer();
}
其他地方的用法:
... App.MyWebServer ...
如果您不想制作靜態變數(盡管恕我直言,這對 App 來說是可以的,因為只有一個,并且它的生命周期是應用程式本身的生命周期),然后洗掉上面的“靜態”,其他地方的用法變為:
... (Xamarin.Forms.Application.Current as App).MyWebServer ...
uj5u.com熱心網友回復:
在這種情況下,可能存在競爭條件。如果兩個(或多個執行緒)Instance第一次同時讀取,將創建多個DataSingleton. 但是,其他所有讀取都只會獲得一個實體。這取決于您的情況,如果可以的話。
public sealed class DataSingleton {
private static instance;
// will assign new DataSingleton only if "instance" is null.
public static Instance => instance ??= new DataSingleton();
}
或者您可以使用Interlocked類確保,instance如果另一個執行緒已經初始化了該instance欄位,則該欄位不會被覆寫。
public sealed class DataSingleton {
private static instance;
public static Instance {
get {
var result = instance;
// early exit if singleton is already initialized
if (result is not null) return result;
var created = new DataSingleton();
// thread-safe way how to assign "created" into "instance" only if "instance" refers to null. othervise no assignment will be made
var original = Interlocked.CompareExchange(ref instance, null, created);
// some other thread already initialized singleton
if (original is not null) return original;
// return newly created instance
return result;
}
}
}
或者您可以使用lock來確保只創建一個實體。
public sealed class DataSingleton {
private static instance;
public static Instance {
get {
var result = instance;
// early exit if singleton is already initialized
if (result is not null) return result;
lock(typeof(DataSingleton)) {
result = instance;
// double check, if instance was not initialized by another thread
if (result is not null) return result;
return instance = new DataSingleton();
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/406445.html
標籤:
