【发布时间】:2010-02-18 10:19:21
【问题描述】:
我有一个通过 C# 远程处理 (System.Runtime.Remoting) 运行的稍微简单的客户端/服务器解决方案。
用于实际通信的 MarshalByRef 对象却让我很困扰。
在其构造函数中,它启动一个外部进程并添加 OutputDataReceived 事件处理程序。
该进程每 2 秒将数据写入其标准输出,然后我在我的事件处理程序中检索并在那里使用。
现在我的问题是如何在这个过程之后进行清理 - 问题是,它无限期地运行,所以我必须调用 Kill() 来停止它。
我尝试在 MarshalByRef 对象的终结器中执行此操作,但这会导致我的应用程序在尝试调用终结器时不时挂起。
远程处理设置为单例,所以它应该是调用终结器的服务器端,所以坦率地说我觉得它不起作用有点奇怪。
产生进程的类实际上是我的 MarshalByRef 对象的一个字段,但这确实不应该有太大变化。
此外,该类在 linux 服务器上以单声道运行,并从工具 mpstat 中读取 CPU 负载。
这是困扰我的课程:
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();
}
}
【问题讨论】: