【问题标题】:Event not firing when running as service作为服务运行时事件未触发
【发布时间】:2012-10-20 03:51:31
【问题描述】:

我有一个在测试模式下运行时运行良好的事件,但在我将代码作为服务运行时不会触发。在发布代码之前,让我先介绍一下应用程序的结构,因为我觉得这就是问题的根源。

我有一个托盘应用程序,用于控制路由器服务。启动时,该服务会加载一个 dll 库,所有处理都在该库中进行。当库启动时,它会扫描一个插件目录,并将它们挂接到主程序中。

当构建为 Release 时,服务被激活,我必须安装应用程序。附带说明一下,托盘应用程序以管理员身份运行,因此它可以控制服务。当构建为 Debug 时,托盘直接启动库 dll,跳过启动它的小型服务应用程序。见下图:

在任何一种情况下,此插件的流程都是 Receiver 接收文件,并通过 Event 通知 Sender 转发它。该文件被发送出去进行远程处理,然后返回到另一个接收器,该接收器通过事件将结果转发给插件。然后插件处理文件,并应在事件中发送回主程序。在调试(无服务)中运行时,这正是发生的情况。当作为服务运行时,除了通知主程序结果已处理的插件外,所有事件处理都可以正常工作。没有抛出异常,我通过日志确认事件已正确连接。

连接事件:

//  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);
        }
    }
}

任何帮助或建议将不胜感激。提前谢谢你。

【问题讨论】:

  • 尝试检查 ExtractResults 函数,那里似乎出了点问题...
  • @Dusan - 感谢您的评论。我用日志帖子填充了该方法,并且知道一切都按预期运行,直到返回。我还检查了它返回的对象,它是按预期创建的。但是,绝对肯定的是,我只是发送了一个新对象而不是从方法中获取它,这导致了一些意外错误。由此,我能够在 OnProcessed 方法中将错误追溯到 SQL 登录问题。再次感谢您的建议。如果您创建回复,我很乐意为您提供信用。
  • 听起来像是权限问题,您可以尝试调整服务使用的用户帐户,看看是否有效?
  • 在服务中勾选“允许服务与桌面交互”,看看是否有效

标签: c# events service delegates


【解决方案1】:

你能检查 Receiver/Sender 对象是否没有被 GC 处理吗?可能是这种情况,因为您的发布和调试的初始化模式不同

【讨论】:

    猜你喜欢
    • 2019-06-18
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 2014-05-17
    相关资源
    最近更新 更多