3

我正在尝试使用 C# 通过 SSH 跟踪文件。该文件从一开始就被读取,然后在保持 SSH 连接的同时继续被监视数小时。我正在使用SSH.NET库为 SSH 提供功能。文件大小最高可达 ~2GB。当前的实现正在运行,但内存使用情况非常糟糕。

测试:为了测试这个功能,我使用 Visual Studio 2012,针对 .NET 框架 4.5,使用下面的代码创建一个小型控制台应用程序。我正在跟踪一个 ~127MB 的静态文件。

问题:从功能上讲,这工作正常,但内存使用情况非常糟糕。应用程序将在调用之前使用 ~7MB shellStream.WriteLine,然后使用 ~144MB 快速增加和平稳(当所有当前文件内容已从流中读取时稳定)。

下面是我尝试使用的代码。

private SshClient sshClient;
private ShellStream shellStream;
//Command being executed to tail a file.
private readonly string command = "tail -f -n+1 {0}";
//EventHandler that is called when new data is received.
public EventHandler<string> DataReceived;

public void TailFile(string server, int port, string userName, string password, string file)
{
   sshClient = new SshClient(server, port, userName, password);
   sshClient.Connect();

   shellStream = sshClient.CreateShellStream("Tail", 0, 0, 0, 0, 1024);

   shellStream.DataReceived += (sender, dataEvent) =>
   {
      if (DataReceived != null)
      {
         DataReceived(this, Encoding.Default.GetString(dataEvent.Data));
      }
   };

   shellStream.WriteLine(string.Format(command, file));
}

是否缺少一些东西来防止内存尽可能多地增加,或者任何其他可以实现相同目标的解决方案?

4

1 回答 1

3

您不使用流中的数据,因此它会累积。

看看事件是如何实现ShellStream.DataReceived

private void Channel_DataReceived(object sender, ChannelDataEventArgs e)
{
    lock (this._incoming)
    {
        // this is where the memory "leaks" as the _incoming is never consumed
        foreach (var b in e.Data)
            this._incoming.Enqueue(b);
    }

    if (_dataReceived != null)
        _dataReceived.Set();

    this.OnDataReceived(e.Data);
}

而不是使用ShellDataEventArgs.Data,使用ShellStream.Read

 shellStream.DataReceived += (sender, dataEvent) =>
 {
    if (DataReceived != null)
    {
       DataReceived(this, shellStream.Read());
    }
 };
于 2015-06-02T06:17:32.943 回答