Skip to content

Commit

Permalink
优化 插件卸载与加载
Browse files Browse the repository at this point in the history
修复 提供Onnx推理环境的插件无法动态卸载
  • Loading branch information
MakesYT committed Feb 24, 2025
1 parent f049d62 commit 4b32108
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 49 deletions.
5 changes: 3 additions & 2 deletions Core/SDKs/Services/Onnx/InferenceSessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ public IInferenceSession GetSession(string modelSignName)
var target= ConfigManger.Config.OnnxTargetDevices.ContainsKey(onnxModelInfoWrapper.Model.SignName)
? ConfigManger.Config.OnnxTargetDevices[onnxModelInfoWrapper.Model.SignName]
: "CPU";
if (!PluginOverall.OnnxRuntimes.ContainsKey(target))
var runtime = PluginOverall.GetOnnxRuntime(target);
if (runtime is null)
{
throw new Exception($"目标推理环境'{target}'不存在");
}
var onnxRuntime = PluginOverall.OnnxRuntimes[target].Invoke();
var onnxRuntime = runtime.Invoke();
if (!File.Exists(onnxModelInfoWrapper.Model.ModelPath))
{
throw new Exception($"模型'{onnxModelInfoWrapper.Model.Name}'不存在,请先下载");
Expand Down
12 changes: 7 additions & 5 deletions Core/SDKs/Services/Plugin/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public Plugin(PluginLocalInfo pluginInfo)
List<Func<string, SearchViewItem?>> searchViews = new();
List<ScreenCaptureExMethod> captureActions = new();
List<OnnxModelInfoWrapper> onnxModelInfos = new();
Dictionary<string,Func<IInferenceSession>> onnxRuntimes = new();
PluginInfo = pluginInfo;
foreach (var type in t)
if (type.GetInterface("IPlugin") != null)
Expand Down Expand Up @@ -134,10 +135,9 @@ public Plugin(PluginLocalInfo pluginInfo)
if (typeof(IInferenceSession).IsAssignableFrom(type))
{
var inferenceSession = (IInferenceSession)ServiceProvider.GetService(type);
if (!PluginOverall.OnnxRuntimes.ContainsKey(inferenceSession.Device))
{
PluginOverall.OnnxRuntimes.Add(inferenceSession.Device, (() => (IInferenceSession)ServiceProvider.GetService(type)));
}

onnxRuntimes.Add(inferenceSession.Device, (() => (IInferenceSession)ServiceProvider.GetService(type)));

}

var scenarioMethodCategoryGroup = pluginMainScenarioMethodCategoryGroup;
Expand Down Expand Up @@ -222,6 +222,7 @@ public Plugin(PluginLocalInfo pluginInfo)
PluginOverall.ScreenCaptureExMethods.Add(PluginInfo.ToPlgString(), captureActions);

PluginOverall.OnnxModelInfos.Add(PluginInfo.ToPlgString(), onnxModelInfos);
PluginOverall.OnnxRuntimes.Add(PluginInfo.ToPlgString(), onnxRuntimes);
}

public Assembly? _dll => _plugin.Assembly;
Expand Down Expand Up @@ -292,7 +293,7 @@ public MethodInfo GetMethod(string methodAbsolutelyName)
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void UnloadByPluginInfo(string pluginInfoEx, out WeakReference weakReference)
{
var plugin = PluginManager.GetPlugin(pluginInfoEx);
var plugin = PluginManager.GetEnablePlugins().TryGetValue(pluginInfoEx, out var value) ? value : null;
if (plugin is not null)
{
plugin.Unload(out weakReference);
Expand All @@ -311,6 +312,7 @@ public void Unload(out WeakReference weakReference)
PluginOverall.SearchActions.Remove(PluginInfo.ToPlgString());
PluginOverall.ScreenCaptureExMethods.Remove(PluginInfo.ToPlgString());
PluginOverall.OnnxModelInfos.Remove(PluginInfo.ToPlgString());
PluginOverall.OnnxRuntimes.Remove(PluginInfo.ToPlgString());
ScenarioMethodCategoryGroup.RootScenarioMethodCategoryGroup.RemoveMethodsByPluginName(PluginInfo.ToPlgString());
var keyValuePairs = CustomScenarioGloble.Triggers.Where(e => e.Value.PluginInfo == PluginInfo.ToPlgString());
foreach (var keyValuePair in keyValuePairs) CustomScenarioGloble.Triggers.Remove(keyValuePair.Key);
Expand Down
62 changes: 44 additions & 18 deletions Core/SDKs/Services/Plugin/PluginManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ public static IEnumerable<PluginLocalInfo> GetPluginLocalInfos()
return AllPluginInfos;
}

public static Plugin? GetPlugin(string plgStr)
public static Dictionary<string,Plugin> GetEnablePlugins()
{
return EnablePlugins.TryGetValue(plgStr, out var value) ? value : null;
return EnablePlugins;
}

public static IServiceProvider GetServiceProvider(string plgStr)
Expand Down Expand Up @@ -168,31 +168,53 @@ public static bool EnablePlugin(string pluginSign)
EnablePlugin(pluginInfoEx);
return true;
}
public static void UnloadPlugin(PluginLocalInfo pluginInfoEx, bool reloadPluginAndCustomScenarion = true)
public static async Task<bool> UnloadPlugin(PluginLocalInfo pluginInfoEx, bool reloadPluginAndCustomScenarion = true)
{
Plugin.UnloadByPluginInfo(pluginInfoEx.ToPlgString(), out var weakReference);
EnablePlugins.Remove(pluginInfoEx.ToPlgString());

ConfigManger.Config.EnabledPluginInfos.RemoveAll(e => e.ToPlgString() == pluginInfoEx.ToPlgString());
ConfigManger.Save();
WeakReference? weakReference=null;
await Task.Run(() =>
{
Plugin.UnloadByPluginInfo(pluginInfoEx.ToPlgString(), out weakReference);
EnablePlugins.Remove(pluginInfoEx.ToPlgString());

for (var i = 0; i < 15; i++)
ConfigManger.Config.EnabledPluginInfos.RemoveAll(e => e.ToPlgString() == pluginInfoEx.ToPlgString());
ConfigManger.Save();

for (var i = 0; i < 30; i++)
{
GC.Collect(2, GCCollectionMode.Aggressive);
GC.WaitForPendingFinalizers();
Task.Delay(50).Wait();
if (!weakReference.IsAlive) break;
}
});
if (weakReference is null)
{
GC.Collect(2, GCCollectionMode.Aggressive);
GC.WaitForPendingFinalizers();
Task.Delay(10).Wait();
return false;
}

if (weakReference.IsAlive) pluginInfoEx.UnloadFailed = true;
if (weakReference.IsAlive)
{
pluginInfoEx.UnloadFailed = true;
Task.Run((() =>
{
while (weakReference.IsAlive)
{
Task.Delay(1000);
}

pluginInfoEx.UnloadFailed = false;
}));
}

// Items.ResetBindings();
if (reloadPluginAndCustomScenarion)
{
WeakReferenceMessenger.Default.Send(
new PluginStateChanged(pluginInfoEx.PluginBaseInfo.NameSign));
Reload();
CustomScenarioManger.Reload();
CustomScenarioManger.Reload();
}
return false;
}

public static void Reload()
Expand Down Expand Up @@ -332,7 +354,7 @@ public static void Load(bool init = false)

foreach (var directoryInfo in pluginsDirectoryInfo.EnumerateDirectories())
{
if (File.Exists($"{directoryInfo.FullName}{Path.DirectorySeparatorChar}.remove"))
if (init&&File.Exists($"{directoryInfo.FullName}{Path.DirectorySeparatorChar}.remove"))
{
try
{
Expand Down Expand Up @@ -390,7 +412,7 @@ public static void Load(bool init = false)
continue;
}
Log.Debug($"加载插件{pluginBaseInfo.Name}信息成功");
if (File.Exists($"{info.Path}.update"))
if (init&&File.Exists($"{info.Path}.update"))
{
var allText = File.ReadAllText($"{info.Path}.update");
if (int.TryParse(allText, out var versionId))
Expand Down Expand Up @@ -500,8 +522,12 @@ public static void DeletePluginWithoutUserCheck(PluginLocalInfo pluginInfoEx)
public static async Task<bool> DownloadPluginAndEnable(int pluginId,string pluginSign, int? targetVersionId = null,
string? targetVersion = null)
{
await DownloadPluginOnline( pluginId, pluginSign, targetVersionId, targetVersion);
return EnablePlugin(pluginSign);
var downloadPluginOnline = await DownloadPluginOnline( pluginId, pluginSign, targetVersionId, targetVersion);
if (downloadPluginOnline)
{
return EnablePlugin(pluginSign);
}
return false;
}

private static async Task<bool> DownloadPlugin(int id, object versionId, string plugin)
Expand Down
11 changes: 8 additions & 3 deletions Core/SDKs/Services/Plugin/PluginOverall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ public class PluginOverall
public static readonly Dictionary<string, List<Func<string, SearchViewItem?>>> SearchActions = new();
public static readonly Dictionary<string, List<ScreenCaptureExMethod>> ScreenCaptureExMethods = new();
public static readonly Dictionary<string,List<OnnxModelInfoWrapper>> OnnxModelInfos = new();
public static readonly Dictionary<string,Func<IInferenceSession>> OnnxRuntimes = new();
public static readonly Dictionary<string,Dictionary<string,Func<IInferenceSession>>> OnnxRuntimes = new();
public static List<OnnxModelInfoWrapper> AllOnnxModelInfos =>
OnnxModelInfos.Values.SelectMany(e => e).ToList();
public static List<string> AllTargetDevices => OnnxRuntimes.Keys.ToList();
public static List<string> AllTargetDevices => OnnxRuntimes.Values.SelectMany(e=>e.Keys).ToList();
public static List<ScreenCaptureExMethod> AllScreenCaptureExMethods =>
ScreenCaptureExMethods.Values.SelectMany(e => e).ToList();

public static Func<IInferenceSession>? GetOnnxRuntime(string targetDevice)
{
var firstOrDefault = OnnxRuntimes.Values.SelectMany(e => e).FirstOrDefault(e => e.Key == targetDevice);

return firstOrDefault.Value??null;
}

}
4 changes: 2 additions & 2 deletions Core/ViewModel/Pages/plugin/PluginManagerPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ private void Delete(PluginInfoUiHelper pluginInfoEx)
}

[RelayCommand]
public void Switch(PluginInfoUiHelper pluginInfoUi)
public async Task Switch(PluginInfoUiHelper pluginInfoUi)
{
var pluginInfoEx = pluginInfoUi.PluginLocalInfo;
Log.Debug(pluginInfoEx.IsEnabled);
if (pluginInfoEx.IsEnabled)
//卸载插件
PluginManager.UnloadPlugin(pluginInfoEx);
await PluginManager.UnloadPlugin(pluginInfoEx);
else
//加载插件
//Plugin.NewPlugin(pluginInfoEx.Path, out var weakReference);
Expand Down
2 changes: 1 addition & 1 deletion KitopiaAvalonia/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public partial class App : Application

public override void Initialize()
{
this.EnableHotReload();
// this.EnableHotReload();
AvaloniaXamlLoader.Load(this);
}

Expand Down
30 changes: 16 additions & 14 deletions KitopiaAvalonia/Controls/DownloadButton.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
xmlns:controls="clr-namespace:KitopiaAvalonia.Controls"
xmlns:pluginCore="clr-namespace:PluginCore;assembly=PluginCore"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="pluginCore:IDownloadButtonViewModel"
x:Class="KitopiaAvalonia.Controls.DownloadButton">
<UserControl.Template>
<ControlTemplate>
<Panel>
<Panel IsVisible="{Binding !IsDownloading}">
<Button Command="{Binding DownloadCommand}"
CommandParameter="{Binding }"
IsVisible="{Binding NeedDownload}"
IsEnabled="{Binding CanDownload}">
<Panel IsVisible="{Binding !IsDownloading, RelativeSource={RelativeSource TemplatedParent}}">
<Button Command="{TemplateBinding DownloadCommand}"
CommandParameter="{TemplateBinding DataContext}"
IsVisible="{TemplateBinding NeedDownload}"
IsEnabled="{TemplateBinding CanDownload}">
<Button.Styles>
<Style Selector="Button[IsEnabled=True]">
<Setter Property="Content">下载</Setter>
Expand All @@ -22,24 +23,25 @@
</Style>
</Button.Styles>
</Button>
<Button IsVisible="{Binding !NeedDownload}"
<Button IsVisible="{Binding !NeedDownload, RelativeSource={RelativeSource TemplatedParent}}"
IsEnabled="False">
已下载
</Button>
</Panel>
<StackPanel Orientation="Horizontal" IsVisible="{Binding IsDownloading}" VerticalAlignment="Center" Margin="15,0,15,0">
<ProgressBar IsIndeterminate="{Binding IsIndeterminate}"
Value="{Binding Progress}"
<StackPanel Orientation="Horizontal" IsVisible="{TemplateBinding IsDownloading}" VerticalAlignment="Center" Margin="15,0,15,0">
<ProgressBar IsIndeterminate="{TemplateBinding IsIndeterminate}"
Value="{TemplateBinding Progress}"

></ProgressBar>
<TextBlock VerticalAlignment="Center" Text="{Binding Progress,StringFormat='{}{0:f2}%' }"></TextBlock>
<Button Command="{Binding CancelCommand}"
CommandParameter="{Binding }">
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Progress,StringFormat='{}{0:f2}%', RelativeSource={RelativeSource TemplatedParent} }"></TextBlock>
<Button Command="{TemplateBinding CancelCommand}"
CommandParameter="{TemplateBinding DataContext}">
取消
</Button>
</StackPanel>

</Panel>


</ControlTemplate>
</UserControl.Template>
</UserControl>
66 changes: 65 additions & 1 deletion KitopiaAvalonia/Controls/DownloadButton.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,75 @@
using Avalonia;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace KitopiaAvalonia.Controls;

public partial class DownloadButton : UserControl
{
/*
* public bool NeedDownload { get; }
public bool CanDownload { get; }
public ICommand DownloadCommand { get; }
public ICommand CancelCommand { get; }
public bool IsIndeterminate { get; }
public bool IsDownloading { get; }
public double Progress { get; }
*/
public static readonly AvaloniaProperty<bool> NeedDownloadProperty =
AvaloniaProperty.Register<DownloadButton, bool>(nameof(NeedDownload), true);
public static readonly AvaloniaProperty<bool> CanDownloadProperty =
AvaloniaProperty.Register<DownloadButton, bool>(nameof(CanDownload), true);
public static readonly AvaloniaProperty<ICommand> DownloadCommandProperty =
AvaloniaProperty.Register<DownloadButton, ICommand>(nameof(DownloadCommand));
public static readonly AvaloniaProperty<ICommand> CancelCommandProperty =
AvaloniaProperty.Register<DownloadButton, ICommand>(nameof(CancelCommand));
public static readonly AvaloniaProperty<bool> IsIndeterminateProperty =
AvaloniaProperty.Register<DownloadButton, bool>(nameof(IsIndeterminate), true);
public static readonly AvaloniaProperty<bool> IsDownloadingProperty =
AvaloniaProperty.Register<DownloadButton, bool>(nameof(IsDownloading), true);
public static readonly AvaloniaProperty<double> ProgressProperty =
AvaloniaProperty.Register<DownloadButton, double>(nameof(Progress), 0.0);


public bool NeedDownload
{
get => (bool)GetValue(NeedDownloadProperty);
set => SetValue(NeedDownloadProperty, value);
}
public bool CanDownload
{
get => (bool)GetValue(CanDownloadProperty);
set => SetValue(CanDownloadProperty, value);
}
public ICommand DownloadCommand
{
get => (ICommand)GetValue(DownloadCommandProperty);
set => SetValue(DownloadCommandProperty, value);
}
public ICommand CancelCommand
{
get => (ICommand)GetValue(CancelCommandProperty);
set => SetValue(CancelCommandProperty, value);
}
public bool IsIndeterminate
{
get => (bool)GetValue(IsIndeterminateProperty);
set => SetValue(IsIndeterminateProperty, value);
}
public bool IsDownloading
{
get => (bool)GetValue(IsDownloadingProperty);
set => SetValue(IsDownloadingProperty, value);
}
public double Progress
{
get => (double)GetValue(ProgressProperty);
set => SetValue(ProgressProperty, value);
}


public DownloadButton()
{
InitializeComponent();
Expand Down
2 changes: 1 addition & 1 deletion KitopiaAvalonia/Pages/HomePage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
xmlns:controls="clr-namespace:KitopiaAvalonia.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="KitopiaAvalonia.Pages.HomePage" x:DataType="pages:HomePageViewModel">
<controls:DownloadButton x:Name="DownloadButton"></controls:DownloadButton>

</UserControl>
11 changes: 10 additions & 1 deletion KitopiaAvalonia/Pages/OnnxModelManagerPage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,16 @@
</DataGridTemplateColumn>
<DataGridTemplateColumn x:DataType="onnx:OnnxModelInfoWrapper" Header="下载模型">
<DataTemplate x:DataType="onnx:OnnxModelInfoWrapper">
<controls:DownloadButton DataContext="{Binding Model }"/>
<controls:DownloadButton DataContext="{Binding Model}"
NeedDownload="{Binding NeedDownload}"
CanDownload="{Binding CanDownload}"
IsDownloading="{Binding IsDownloading}"
IsIndeterminate="{Binding IsIndeterminate}"
Progress="{Binding Progress}"
DownloadCommand="{Binding DownloadCommand}"
CancelCommand="{Binding CancelCommand}"

/>
</DataTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
Expand Down
3 changes: 3 additions & 0 deletions KitopiaAvalonia/Pages/PluginManagerPage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
<Style Selector="ToggleButton[IsChecked=False]">
<Setter Property="Content" Value="启用" />
</Style>
<Style Selector="ToggleButton[IsChecked=False].Danger">
<Setter Property="Content" Value="卸载中" />
</Style>
</ToggleButton.Styles>
</ToggleButton>
</StackPanel>
Expand Down
2 changes: 1 addition & 1 deletion PluginCore

0 comments on commit 4b32108

Please sign in to comment.