2012-10-30 33 views
5

運行時,我在測試模式下運行時工作得很好,但是當我運行的代碼作爲服務不火的事件不點火。在我發佈代碼之前,讓我介紹一下應用程序的結構,因爲我覺得這是問題的起因。事件作爲服務

我有一個用來控制一個路由器服務的托盤的應用程序。啓動時,該服務會加載一個所有處理髮生的dll庫。當庫啓動時,它會掃描目錄中的插件,並將它們掛接到主程序中。

當作爲發佈建成,該服務被激活了,我必須安裝應用程序。作爲一個側面說明,托盤應用程序以管理員身份運行,因此它可以控制服務。當構建爲Debug時,該托盤直接啓動庫DLL,跳過啓動它的小型服務應用程序。請參見下面的圖:

enter image description here

在任一情況下,此插件的流動是一個接收器接收到的文件,並通知發送方通過一個事件轉發它。該文件被髮送以進行遠程處理,然後返回到另一個Receiver,該Receiver通過事件將結果轉發給插件。然後該插件處理該文件,並且應該在事件中發送回主程序。在Debug(無服務)下運行時,這正是發生的情況。作爲服務運行時,除了通知主程序處理結果的插件外,所有的事件處理都可以完美工作。沒有拋出異常,並且我已通過日誌記錄證實事件已正確連接。

連接事件:

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

任何幫助或建議,將不勝感激。先謝謝你。

+1

嘗試檢查ExtractResults功能,似乎是不順心的事有... – Dusan

+0

@Dusan - 謝謝你的評論。我用日誌帖子填充了方法,並知道一切都按預期運行,直到回報。我還檢查了它正在返回的對象,它是按照它應該創建的。但是,爲了絕對肯定,我只是發送了一個新對象,而不是從方法中獲取它,並導致了一些意外錯誤。從那以後,我能夠在OnProcessed方法中追蹤到SQL登錄問題的錯誤。再次感謝您的建議。如果您創建回覆,我會很樂意爲您提供信用。 – Tim

+0

聽起來像一個權限問題,你可以嘗試調整服務使用的用戶帳戶,看看是否有效? –

回答

0

你可以檢查是否接收器/發送者的物體是不是GCed?這可能是這種情況,作爲發佈和調試你的初始化模式是不同的