使用带有SSH.NET的C#通过SSH流式传输/拖尾数据会泄漏内存

时间:2015-06-01 16:23:52

标签: c# ssh tail ssh.net

我正在尝试使用C#在SSH上拖尾文件。此文件从头开始读取,然后继续监视几个小时,同时保持SSH连接。我正在使用SSH.NET库来为SSH提供功能。文件大小可以高达~2GB。当前的实现正在运行,但内存使用情况非常糟糕。

测试:为了测试此功能,我使用面向.NET framework 4.5的Visual Studio 2012,使用下面的代码创建一个小型控制台应用程序。我正在拖尾一个大约127MB的静态文件。

问题:从功能上来说这很好用,但内存使用情况非常糟糕。在shellStream.WriteLine被调用之前,应用程序将使用~7MB,然后使用~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));
}

是否有某些东西缺失以防止内存增加,或者任何其他可以实现相同目标的解决方案?

1 个答案:

答案 0 :(得分:2)

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

请参阅how the ShellStream.DataReceived event is implemented

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