2010-02-18 11 views
0

J'ai une solution Client/Serveur quelque peu simple qui exécute la commande à distance C# (System.Runtime.Remoting).Nettoyage du serveur après l'accès à distance C#

L'objet MarshalByRef, qui est utilisé pour la communication actuelle, me perturbe cependant.

Dans son constructeur, il démarre un processus externe et ajoute le gestionnaire d'événement OutputDataReceived.

Toutes les 2 secondes, le processus écrit des données dans sa sortie stdout, que je récupère ensuite dans mon eventhandler et que j'utilise ici.

Maintenant, mon problème est de savoir comment nettoyer après ce processus - la chose est, il s'exécute indéfiniment, donc je dois appeler Kill() pour l'arrêter.

J'ai essayé de le faire dans le finaliseur de l'objet MarshalByRef, mais cela a provoqué le blocage de mon application de temps en temps, lorsque j'essayais d'appeler le finaliseur.

L'accès à distance est configuré comme un Singleton, donc ce devrait être le côté serveur qui appelle le finaliseur, donc franchement, je trouve ça un peu étrange que ça ne marche pas.

La classe qui génère le processus est en fait un champ de mon objet MarshalByRef, mais cela ne devrait pas vraiment changer beaucoup.

La classe est également exécutée en mono sur un serveur Linux et lit la charge du processeur à partir de l'outil mpstat.

Voici la classe qui me trouble:

internal class CpuInfo 
{ 
    private Regex parser = new Regex(@"\d{2}:\d{2}:\d{2}\s+(?<CpuID>\d{1,2}).*?(?<IdlePercentage>\d{1,2},\d{1,2})(\r|\n|$)", RegexOptions.Compiled | RegexOptions.Multiline); 
    private Process proc; 
    private IDictionary<int, long> cpuLoads; 
    internal CpuInfo() 
    { 
     cpuLoads = new Dictionary<int, long>(); 
     proc = new Process(); 
     proc.StartInfo.UseShellExecute = false; 
     proc.StartInfo.CreateNoWindow = true; 
     proc.StartInfo.Arguments = "-u -P ALL 2"; 
     proc.StartInfo.FileName = "mpstat"; 
     proc.StartInfo.RedirectStandardOutput = true; 
     proc.EnableRaisingEvents = true; 
     proc.OutputDataReceived += proc_OutputDataReceived; 

     proc.Start(); 
     proc.BeginOutputReadLine(); 
    } 

    void proc_OutputDataReceived(object sender, DataReceivedEventArgs e) 
    { 
     Match match = parser.Match(e.Data); 
     if (match.Success) 
     { 
      int cpuID = int.Parse(match.Groups["CpuID"].Value); 
      string idleValue = match.Groups["IdlePercentage"].Value.Replace(',', '.'); 
      decimal idle = decimal.Parse(idleValue, CultureInfo.InvariantCulture); 
      cpuLoads[cpuID] = (long)((100m - idle) * 100); 
     } 
    } 

    ~CpuInfo() 
    { 
     proc.OutputDataReceived -= proc_OutputDataReceived; 
     proc.Kill(); 
    } 
} 

Répondre

0

figured it moi-même maintenant - j'utilise RemoteServices.Marshal Serverside et RemoteServices.Connect clientside. De cette façon, ma référence d'objet existe sur le serveur, et je peux utiliser IDisposable pour le nettoyage.