Очистка серверной части после удаленного взаимодействия C # - PullRequest
0 голосов
/ 18 февраля 2010

У меня есть несколько простое клиент-серверное решение, работающее на C # remoting (System.Runtime.Remoting).

Однако объект MarshalByRef, который используется для реального обмена данными, меня беспокоит.

В своем конструкторе он запускает внешний процесс и добавляет обработчик события OutputDataReceived.

Каждые 2 секунды процесс будет записывать данные в свой стандартный вывод, который я затем получаю в своем обработчике событий и использую там.

Теперь моя проблема в том, как выполнить очистку после этого процесса - дело в том, что он работает бесконечно, поэтому мне нужно вызвать Kill (), чтобы остановить его.

Я пытался сделать это в финализаторе объекта MarshalByRef, однако это иногда приводило к зависанию моего приложения при попытке вызова финализатора.

Remoting настроен как Singleton, поэтому он должен быть на стороне сервера, который вызывает финализатор, так что, откровенно говоря, я нахожу это немного странным, он не работает

Класс, который порождает процесс, на самом деле является полем моего объекта MarshalByRef, но это не должно сильно измениться.

Также класс запускается в моно на сервере linux и считывает загрузку процессора из инструмента mpstat.

Вот класс, который меня беспокоит:

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

1 Ответ

0 голосов
/ 08 марта 2010

Сам разобрался сейчас - я использую серверную часть RemoteServices.Marshal и клиентскую часть RemoteServices.Connect. Таким образом, моя ссылка на объект существует на стороне сервера, и я могу использовать IDisposable для хорошей очистки.

...