优化资源加载

This commit is contained in:
小红帽 2024-04-18 14:44:36 +08:00
parent a942ee6c2e
commit 379d2367f3
2 changed files with 139 additions and 39 deletions

View File

@ -184,6 +184,8 @@ namespace CPF.Linux
else else
{ {
XLib.XReparentWindow(x11info.Display, Handle, x11info.Info.DefaultRootWindow, 0, 0); XLib.XReparentWindow(x11info.Display, Handle, x11info.Info.DefaultRootWindow, 0, 0);
visible = false;
XLib.XUnmapWindow(x11info.Display, Handle);
} }
this.parent = parent as X11Window; this.parent = parent as X11Window;
} }

View File

@ -17,16 +17,37 @@ namespace CPF.Styling
/// </summary> /// </summary>
public class ResourceManager public class ResourceManager
{ {
//private static Encoding s_defaultEncoding = Encoding.UTF8;
internal class ResourceCache
{
internal Assembly _assembly;
internal HashSet<string> _resourceKeys;
//internal ConcurrentDictionary<string, WeakReference<string>> _stringCache;
//internal ConcurrentDictionary<string, WeakReference<Image>> _imageCache;
internal ResourceCache(Assembly assembly)
{
_assembly = assembly;
var ns = assembly.GetManifestResourceNames();
_resourceKeys = new HashSet<string>();
foreach (var item in ns)
{
_resourceKeys.Add(item);
}
//_stringCache = new ConcurrentDictionary<string, WeakReference<string>>();
//_imageCache = new ConcurrentDictionary<string, WeakReference<Image>>();
}
}
static List<ResourceCache> s_cacheList;
static ReaderWriterLockSlim s_lock;
static ResourceManager() static ResourceManager()
{ {
//Register(Assembly.GetExecutingAssembly()); s_cacheList = new List<ResourceCache>();
//Register(Assembly.GetEntryAssembly()); s_lock = new ReaderWriterLockSlim();
//Register(Assembly.GetCallingAssembly());
foreach (var item in AppDomain.CurrentDomain.GetAssemblies())
{
Register(item);
}
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
Register(assembly);
}
} }
private static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args) private static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
@ -34,7 +55,7 @@ namespace CPF.Styling
Register(args.LoadedAssembly); Register(args.LoadedAssembly);
} }
static Dictionary<string, Assembly> assemblies = new Dictionary<string, Assembly>(); //static Dictionary<string, Assembly> assemblies = new Dictionary<string, Assembly>();
/// <summary> /// <summary>
/// 注册资源程序集,资源必须是内嵌的才能读取,程序集名称不能重复。一般情况下会自动注册,不需要手动调用 /// 注册资源程序集,资源必须是内嵌的才能读取,程序集名称不能重复。一般情况下会自动注册,不需要手动调用
/// </summary> /// </summary>
@ -45,20 +66,63 @@ namespace CPF.Styling
{ {
return; return;
} }
if (assemblies.ContainsKey(assembly.FullName)) if (assembly.IsDynamic || string.IsNullOrEmpty(assembly.FullName))
return;
s_lock.EnterWriteLock();
try
{ {
assemblies.Remove(assembly.FullName); var rc = new ResourceCache(assembly);
if (rc._resourceKeys.Count > 0)
{
s_cacheList.Add(rc);
} }
assemblies.Add(assembly.FullName, assembly);
} }
finally
{
s_lock.ExitWriteLock();
}
}
public static void Unregister(Assembly assembly)
{
s_lock.EnterWriteLock();
try
{
for (int i = 0; i < s_cacheList.Count; i++)
{
if (s_cacheList[i]._assembly == assembly)
{
s_cacheList.RemoveAt(i);
i--;
}
}
}
finally
{
s_lock.ExitWriteLock();
}
}
/// <summary> /// <summary>
/// 移除程序集 /// 移除程序集
/// </summary> /// </summary>
public static void RemoveAssembly(string assemblyFullName) public static void RemoveAssembly(string assemblyFullName)
{ {
if (assemblies.ContainsKey(assemblyFullName)) s_lock.EnterWriteLock();
try
{ {
assemblies.Remove(assemblyFullName); for (int i = 0; i < s_cacheList.Count; i++)
{
if (s_cacheList[i]._assembly.FullName == assemblyFullName)
{
s_cacheList.RemoveAt(i);
i--;
}
}
}
finally
{
s_lock.ExitWriteLock();
} }
} }
@ -135,10 +199,11 @@ namespace CPF.Styling
/// </summary> /// </summary>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="action"></param> /// <param name="action"></param>
public static void GetImage(string path, Action<Image> action) /// <param name="cache">是否弱引用缓存资源</param>
public static void GetImage(string path, Action<Image> action, bool cache = true)
{ {
Image img = null; Image img = null;
if (!res.TryGetValue(path, out WeakReference<Image> image) || !image.TryGetTarget(out img)) if (!res.TryGetValue(path, out WeakReference<Image> image) || !image.TryGetTarget(out img) || img.ImageImpl == null)
{ {
res.TryRemove(path, out var v); res.TryRemove(path, out var v);
var lower = path.ToLower(); var lower = path.ToLower();
@ -169,7 +234,10 @@ namespace CPF.Styling
using (Stream stream = response.GetResponseStream()) using (Stream stream = response.GetResponseStream())
{ {
img = Image.FromStream(stream); img = Image.FromStream(stream);
if (cache)
{
res.TryAdd(path, new WeakReference<Image>(img)); res.TryAdd(path, new WeakReference<Image>(img));
}
//action(img); //action(img);
} }
} }
@ -202,22 +270,30 @@ namespace CPF.Styling
if (!string.IsNullOrWhiteSpace(CPF.Design.DesignerLoadStyleAttribute.ProjectPath) && File.Exists(Path.Combine(CPF.Design.DesignerLoadStyleAttribute.ProjectPath, str.Substring(l + 1)))) if (!string.IsNullOrWhiteSpace(CPF.Design.DesignerLoadStyleAttribute.ProjectPath) && File.Exists(Path.Combine(CPF.Design.DesignerLoadStyleAttribute.ProjectPath, str.Substring(l + 1))))
{ {
var image1 = Image.FromFile(Path.Combine(CPF.Design.DesignerLoadStyleAttribute.ProjectPath, str.Substring(l + 1))); var image1 = Image.FromFile(Path.Combine(CPF.Design.DesignerLoadStyleAttribute.ProjectPath, str.Substring(l + 1)));
if (cache)
{
res.TryAdd(path, new WeakReference<Image>(image1)); res.TryAdd(path, new WeakReference<Image>(image1));
}
action(image1); action(image1);
} }
else else
{ {
var name = str.Substring(0, l) + ","; //var name = str.Substring(0, l) + ",";
Image image1 = null; Image image1 = null;
foreach (var item in assemblies) var p = str.Replace('/', '.').Replace('\\', '.');
for (int i = 0; i < s_cacheList.Count; i++)
{ {
if (item.Value.FullName.StartsWith(name)) ResourceCache last = s_cacheList[s_cacheList.Count - i - 1];
if (last._resourceKeys.Contains(p))
{ {
Stream fs = item.Value.GetManifestResourceStream(str.Replace('/', '.').Replace('\\', '.')); Stream fs = last._assembly.GetManifestResourceStream(p);
if (fs != null) if (fs != null)
{ {
var im = Image.FromStream(fs); var im = Image.FromStream(fs);
if (cache)
{
res.TryAdd(path, new WeakReference<Image>(im)); res.TryAdd(path, new WeakReference<Image>(im));
}
fs.Dispose(); fs.Dispose();
image1 = im; image1 = im;
} }
@ -244,8 +320,11 @@ namespace CPF.Styling
{ {
var b = Convert.FromBase64String(path.Substring(s + 1)); var b = Convert.FromBase64String(path.Substring(s + 1));
i = Image.FromBuffer(b); i = Image.FromBuffer(b);
if (cache)
{
res.TryAdd(path, new WeakReference<Image>(i)); res.TryAdd(path, new WeakReference<Image>(i));
} }
}
catch (Exception e) catch (Exception e)
{ {
Debug.WriteLine("解析图片出错:" + (path.Length > 100 ? path.Substring(0, 100) : path) + e); Debug.WriteLine("解析图片出错:" + (path.Length > 100 ? path.Substring(0, 100) : path) + e);
@ -267,8 +346,11 @@ namespace CPF.Styling
using (var im = Image.FromFile(s)) using (var im = Image.FromFile(s))
{ {
i = im.Clone() as Image; i = im.Clone() as Image;
if (cache)
{
res.TryAdd(path, new WeakReference<Image>(i)); res.TryAdd(path, new WeakReference<Image>(i));
} }
}
action(i); action(i);
} }
catch (Exception e) catch (Exception e)
@ -289,7 +371,8 @@ namespace CPF.Styling
/// </summary> /// </summary>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="action"></param> /// <param name="action"></param>
public static void GetText(string path, Action<string> action) /// <param name="cache"></param>
public static void GetText(string path, Action<string> action, bool cache = true)
{ {
if (!texts.TryGetValue(path, out string text)) if (!texts.TryGetValue(path, out string text))
{ {
@ -318,10 +401,13 @@ namespace CPF.Styling
{ {
text = text.TrimStart((char)65279); text = text.TrimStart((char)65279);
} }
if (cache)
{
texts.Add(path, text); texts.Add(path, text);
} }
} }
} }
}
catch (Exception e) catch (Exception e)
{ {
Debug.WriteLine("加载网页失败:" + path + " " + e.Message); Debug.WriteLine("加载网页失败:" + path + " " + e.Message);
@ -349,12 +435,14 @@ namespace CPF.Styling
} }
else else
{ {
var name = str.Substring(0, l) + ","; //var name = str.Substring(0, l) + ",";
foreach (var item in assemblies) var p = str.Replace('/', '.').Replace('\\', '.');
for (int i = 0; i < s_cacheList.Count; i++)
{ {
if (item.Value.FullName.StartsWith(name)) ResourceCache last = s_cacheList[s_cacheList.Count - i - 1];
if (last._resourceKeys.Contains(p))
{ {
Stream fs = item.Value.GetManifestResourceStream(str.Replace('\\', '.').Replace('/', '.')); Stream fs = last._assembly.GetManifestResourceStream(p);
if (fs != null) if (fs != null)
{ {
var data = new byte[fs.Length]; var data = new byte[fs.Length];
@ -364,7 +452,10 @@ namespace CPF.Styling
{ {
text = text.TrimStart((char)65279); text = text.TrimStart((char)65279);
} }
if (cache)
{
texts.Add(path, text); texts.Add(path, text);
}
fs.Dispose(); fs.Dispose();
} }
break; break;
@ -393,8 +484,11 @@ namespace CPF.Styling
{ {
text = text.TrimStart((char)65279); text = text.TrimStart((char)65279);
} }
if (cache)
{
texts.Add(path, text); texts.Add(path, text);
} }
}
catch (Exception e) catch (Exception e)
{ {
Debug.WriteLine("加载文本失败:" + path + " " + e.Message); Debug.WriteLine("加载文本失败:" + path + " " + e.Message);
@ -409,8 +503,9 @@ namespace CPF.Styling
/// 读取文件或者内嵌或者网络的文本,弱引用缓存。 /// 读取文件或者内嵌或者网络的文本,弱引用缓存。
/// </summary> /// </summary>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="cache"></param>
/// <returns></returns> /// <returns></returns>
public static Task<string> GetText(string path) public static Task<string> GetText(string path, bool cache = true)
{ {
//var task = Task.Factory.StartNew(() => //var task = Task.Factory.StartNew(() =>
//{ //{
@ -422,7 +517,7 @@ namespace CPF.Styling
completionSource.SetResult(a); completionSource.SetResult(a);
//result = a; //result = a;
//invokeMre.Set(); //invokeMre.Set();
}); }, cache);
//invokeMre.WaitOne(); //invokeMre.WaitOne();
//return result; //return result;
return completionSource.Task; return completionSource.Task;
@ -433,8 +528,9 @@ namespace CPF.Styling
/// 读取文件或者内嵌或者网络的图片,弱引用缓存 /// 读取文件或者内嵌或者网络的图片,弱引用缓存
/// </summary> /// </summary>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="cache"></param>
/// <returns></returns> /// <returns></returns>
public static Task<Image> GetImage(string path) public static Task<Image> GetImage(string path, bool cache = true)
{ {
var task = Task.Factory.StartNew(() => var task = Task.Factory.StartNew(() =>
{ {
@ -444,7 +540,7 @@ namespace CPF.Styling
{ {
result = a; result = a;
invokeMre.Set(); invokeMre.Set();
}); }, cache);
invokeMre.WaitOne(); invokeMre.WaitOne();
return result; return result;
}); });
@ -497,11 +593,13 @@ namespace CPF.Styling
var l = str.IndexOf('/'); var l = str.IndexOf('/');
var name = str.Substring(0, l) + ","; var name = str.Substring(0, l) + ",";
Stream fs = null; Stream fs = null;
foreach (var item in assemblies) var p = str.Replace('/', '.').Replace('\\', '.');
for (int i = 0; i < s_cacheList.Count; i++)
{ {
if (item.Value.FullName.StartsWith(name)) ResourceCache last = s_cacheList[s_cacheList.Count - i - 1];
if (last._resourceKeys.Contains(p))
{ {
fs = item.Value.GetManifestResourceStream(str.Replace('/', '.').Replace('\\', '.')); fs = last._assembly.GetManifestResourceStream(p);
//if (fs != null) //if (fs != null)
//{ //{
// var data = new byte[fs.Length]; // var data = new byte[fs.Length];