fix: SqliteConnectionTracker — AssemblyReloadEvents.beforeAssemblyReload 安全关闭
- 静态追踪所有 SQLiteConnection,domain reload 前 Dispose 全部 - 替换所有 GC.Collect+WaitForPendingFinalizers 为 Tracker 模式 - DatabaseManager、ScenarioManager、中、SimulationRunner 等全部 Track/Untrack
This commit is contained in:
parent
5c23e92587
commit
a19dced505
@ -19,10 +19,11 @@ namespace CounterDrone.Unity
|
||||
{
|
||||
var paths = new UnityPathProvider();
|
||||
_db = new DatabaseManager(paths).OpenMainDb();
|
||||
SqliteConnectionTracker.Track(_db);
|
||||
_service = new GroupService(new GroupRepository(_db));
|
||||
}
|
||||
|
||||
void OnDisable() { _db?.Dispose(); _db = null; GC.Collect(); GC.WaitForPendingFinalizers(); }
|
||||
void OnDisable() { SqliteConnectionTracker.Untrack(_db); _db?.Dispose(); _db = null; }
|
||||
|
||||
public Group Create(string name, GroupType type, string desc = "")
|
||||
=> _service.CreateGroup(name, type, desc);
|
||||
|
||||
@ -49,6 +49,7 @@ namespace CounterDrone.Unity
|
||||
Debug.Log("3. Scenario configured");
|
||||
|
||||
var db = new DatabaseManager(paths).OpenMainDb();
|
||||
SqliteConnectionTracker.Track(db);
|
||||
foreach (var a in DefaultAmmunition.GetAll()) db.Insert(a);
|
||||
var ammoCatalog = db.Table<AmmunitionSpec>().ToList();
|
||||
|
||||
@ -93,7 +94,8 @@ namespace CounterDrone.Unity
|
||||
ReleaseAltitude = u.ReleaseAltitude > 0 ? u.ReleaseAltitude : null,
|
||||
});
|
||||
scenarioMgr.SaveDeployment(taskId, equips);
|
||||
db.Close();
|
||||
SqliteConnectionTracker.Untrack(db);
|
||||
db.Dispose();
|
||||
var plan = result.Best;
|
||||
Debug.Log($"4. Plan: {plan.ThreatsEngaged} threats engaged, {plan.MergedSchedule.Count} rounds, prob={plan.OverallProbability:P0}");
|
||||
|
||||
|
||||
@ -21,10 +21,11 @@ namespace CounterDrone.Unity
|
||||
{
|
||||
_paths = new UnityPathProvider();
|
||||
_db = new DatabaseManager(_paths).OpenMainDb();
|
||||
SqliteConnectionTracker.Track(_db);
|
||||
_service = new ModelService(new ModelRepository(_db), _paths);
|
||||
}
|
||||
|
||||
void OnDisable() { _db?.Dispose(); _db = null; GC.Collect(); GC.WaitForPendingFinalizers(); }
|
||||
void OnDisable() { SqliteConnectionTracker.Untrack(_db); _db?.Dispose(); _db = null; }
|
||||
|
||||
public ModelInfo Import(string filePath, string name) => _service.ImportModel(filePath, name);
|
||||
public void Delete(string id) => _service.DeleteModel(id);
|
||||
|
||||
@ -19,10 +19,11 @@ namespace CounterDrone.Unity
|
||||
{
|
||||
_paths = new UnityPathProvider();
|
||||
_db = new DatabaseManager(_paths).OpenMainDb();
|
||||
SqliteConnectionTracker.Track(_db);
|
||||
_service = new ReportService(_db, _paths);
|
||||
}
|
||||
|
||||
void OnDisable() { _db?.Dispose(); _db = null; GC.Collect(); GC.WaitForPendingFinalizers(); }
|
||||
void OnDisable() { SqliteConnectionTracker.Untrack(_db); _db?.Dispose(); _db = null; }
|
||||
|
||||
public SimulationReport Generate(string taskId, TaskFullConfig cfg, List<SimEvent> events, string status, float duration)
|
||||
=> _service.Generate(taskId, cfg, events, status, duration);
|
||||
|
||||
@ -22,6 +22,7 @@ namespace CounterDrone.Unity
|
||||
var paths = new UnityPathProvider();
|
||||
Debug.Log($"ScenarioManager.Awake: dbPath={paths.GetMainDbPath()}");
|
||||
_db = new DatabaseManager(paths).OpenMainDb();
|
||||
SqliteConnectionTracker.Track(_db);
|
||||
_service = new ScenarioService(
|
||||
new SimTaskRepository(_db), new CombatSceneRepository(_db),
|
||||
new ControlZoneRepository(_db), new TargetConfigRepository(_db),
|
||||
@ -35,7 +36,7 @@ namespace CounterDrone.Unity
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable() { _db?.Dispose(); _db = null; GC.Collect(); GC.WaitForPendingFinalizers(); }
|
||||
void OnDisable() { SqliteConnectionTracker.Untrack(_db); _db?.Dispose(); _db = null; }
|
||||
|
||||
public SimTask CreateTask(string name, string number) => _service.CreateTask(name, number);
|
||||
public void DeleteTask(string id) => _service.DeleteTask(id);
|
||||
|
||||
@ -33,6 +33,7 @@ namespace CounterDrone.Unity
|
||||
|
||||
var dbm = new DatabaseManager(paths);
|
||||
var db = dbm.OpenMainDb();
|
||||
SqliteConnectionTracker.Track(db);
|
||||
foreach (var a in DefaultAmmunition.GetAll()) db.Insert(a);
|
||||
|
||||
// 创建想定
|
||||
@ -109,7 +110,8 @@ namespace CounterDrone.Unity
|
||||
});
|
||||
scenario.SaveDeployment(taskId, equips);
|
||||
|
||||
db.Close();
|
||||
SqliteConnectionTracker.Untrack(db);
|
||||
db.Dispose();
|
||||
|
||||
var plan = result.Best;
|
||||
Debug.Log($"规划方案: {plan.ThreatsEngaged} 威胁被分配, {plan.MergedSchedule.Count} 发, 概率 {plan.OverallProbability:P0}");
|
||||
|
||||
@ -39,6 +39,7 @@ namespace CounterDrone.Unity
|
||||
{
|
||||
_paths = new UnityPathProvider();
|
||||
_db = new DatabaseManager(_paths).OpenMainDb();
|
||||
SqliteConnectionTracker.Track(_db);
|
||||
|
||||
_scenario = new ScenarioService(
|
||||
new SimTaskRepository(_db), new CombatSceneRepository(_db),
|
||||
@ -149,7 +150,7 @@ namespace CounterDrone.Unity
|
||||
}
|
||||
|
||||
public void Stop() => _engine?.Stop();
|
||||
void OnDisable() { _db?.Dispose(); _db = null; GC.Collect(); GC.WaitForPendingFinalizers(); }
|
||||
void OnDisable() { SqliteConnectionTracker.Untrack(_db); _db?.Dispose(); _db = null; }
|
||||
void OnDestroy() => Stop();
|
||||
|
||||
private void SpawnDroneVisual(DroneEntity drone)
|
||||
|
||||
45
src/Unity/Assets/Scripts/Managers/SqliteConnectionTracker.cs
Normal file
45
src/Unity/Assets/Scripts/Managers/SqliteConnectionTracker.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using SQLite;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace CounterDrone.Unity
|
||||
{
|
||||
/// <summary>追踪所有打开的 SQLite 连接,在 domain reload 前安全关闭</summary>
|
||||
public static class SqliteConnectionTracker
|
||||
{
|
||||
private static readonly List<SQLiteConnection> _connections = new();
|
||||
|
||||
static SqliteConnectionTracker()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
AssemblyReloadEvents.beforeAssemblyReload += DisposeAll;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Track(SQLiteConnection db)
|
||||
{
|
||||
lock (_connections) { _connections.Add(db); }
|
||||
}
|
||||
|
||||
public static void Untrack(SQLiteConnection db)
|
||||
{
|
||||
lock (_connections) { _connections.Remove(db); }
|
||||
}
|
||||
|
||||
private static void DisposeAll()
|
||||
{
|
||||
lock (_connections)
|
||||
{
|
||||
foreach (var db in _connections)
|
||||
{
|
||||
try { db.Dispose(); }
|
||||
catch { /* absorb */ }
|
||||
}
|
||||
_connections.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user