我有一个在测试模式下运行时运行良好的事件,但在我将代码作为服务运行时不会触发。在发布代码之前,让我先介绍一下应用程序的结构,因为我觉得这就是问题的根源。
我有一个用于控制路由器服务的托盘应用程序。启动时,该服务会加载一个 dll 库,所有处理都在该库中进行。当库启动时,它会扫描一个目录以查找插件,并将它们挂接到主程序中。
当构建为 Release 时,服务被激活,我必须安装应用程序。附带说明一下,托盘应用程序以管理员身份运行,因此它可以控制服务。当构建为 Debug 时,托盘直接启动库 dll,跳过启动它的小型服务应用程序。见下图:
在任何一种情况下,此插件的流程都是 Receiver 接收文件,并通知 Sender 通过 Event 转发它。该文件被发送出去进行远程处理,然后返回到另一个接收器,该接收器通过事件将结果转发给插件。然后插件处理文件,并应在事件中发送回主程序。在调试(无服务)中运行时,这正是发生的情况。当作为服务运行时,除了通知主程序结果已处理的插件外,所有事件处理都可以完美运行。没有抛出异常,我通过记录确认事件已正确连接。
连接事件:
// Connect delegate to plugins that will add data to the database through the Router
if (plugin is INotify)
{
((INotify)plugin).NotifyProcessingComplete += new ProcessNotification(this.OnProcessed);
LogWriter.Log("Associated " + plugin.Name + " with OnProcessed", LogFile);
}
从插件调用事件:
if (NotifyProcessingComplete != null)
NotifyProcessingComplete(ExtractResults(args.ReceivedFile));
else
LogWriter.Log("NotifyProcessingComplete Delegate was null.", LogFile);
事件处理程序:
public void OnProcessed(ProcessArgs args)
{
LogWriter.Log("On Dicom Process was called...", LogFile);
lock (threadLock)
{
if (Settings != null)
{ ... }
}
}
根据日志,插件已正确连接到 OnProcessed,并且登录 ExtractResults() 方法表明它正在正确返回。但是,NotifyProcessingComplete 没有调用 OnProcessed 方法。
再一次,这仅在将代码作为服务运行时才会发生。我怀疑这可能与以管理员身份运行的托盘、以本地系统运行的服务以及动态加载的插件有关。
下面我包含了加载插件的代码,以防它可能有帮助:
private void loadPlugins()
{
String pluginPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// Create a domain to text for plugins
AppDomain domain = AppDomain.CreateDomain("PluginLoader");
PluginFinder finder = (PluginFinder)domain.CreateInstanceAndUnwrap(
typeof(PluginFinder).Assembly.FullName, typeof(PluginFinder).FullName);
finder.LogFile = logFile;
// Get valid plugins, and then unload the domain to clear up memory
List<String> FoundPluginTypes = finder.SearchPath(pluginPath);
AppDomain.Unload(domain);
// Load the plugins
Plugins = new List<IPlugin>();
foreach (String plugin in FoundPluginTypes)
{
Assembly assembly = Assembly.LoadFrom(plugin);
Type type = null;
foreach (Type t in assembly.GetTypes())
if (t.GetInterface("IPlugin") != null)
type = t;
try
{
IPlugin loader = (IPlugin)Activator.CreateInstance(type);
Plugins.Add(loader);
}
catch (NullReferenceException e)
{
LogWriter.Log("Could not load plugin.", e, LogFile);
}
}
}
任何帮助或建议将不胜感激。先感谢您。