将进度栏与C#控制台应用程序一起使用

时间:2018-08-25 20:41:15

标签: c# progress-bar console-application

我想在我的SFTP下载中包含一个进度条,以便用户理解这只是一个大文件,并且进度没有冻结/锁定。我偶然发现了this的nuget程序包,它看起来确实可以满足我的需要,但是由于我使用的是SFTP,因此要获取正在下载的文件的总文件大小,并希望更新进度条尽可能真实地取决于已传输了多少文件。

如果我正确理解此代码-我将仅提供“总滴答”计数,该计数与文件大小完全无关,因此进度指示将不准确。如何根据文件大小显示实际进度?

const int totalTicks = 10;
var options = new ProgressBarOptions
{
  ProgressCharacter = '─',
  ProgressBarOnBottom = true
};
using (var pbar = new ProgressBar(totalTicks, "Initial message", options))
{
  pbar.Tick(); //will advance pbar to 1 out of 10.
  //we can also advance and update the progressbar text
  pbar.Tick("Step 2 of 10"); 
}

修改

经过一些谷歌搜索和大量的反复试验后,我想到了下面的语法,其功能几乎与我想要的一样。我的问题是进度条将仅显示FIRST文件的进度,因此它将“紧密地”显示第一个文件的文件传输进度,当达到100%时,它只会坐在那里而不会显示进度后续文件。

我需要在下面的代码中进行哪些更改,以显示从目录下载的所有文件的文件进度?

注意***以下代码中未声明的任何变量在我的代码中都声明为私有const变量

static void Main(string[] args)
{
    var options = new ProgressBarOptions
    {
        ProgressCharacter = '.',
        ProgressBarOnBottom = true
    };
    using (var pbar = new ProgressBar(totalTicks, "Starting To Download Files....", options))
        DownloadFile(spvalues.an, spvalues.lt, b, d, username, password, pbar, totalTicks, 500);    
}

private static void DownloadFile(string username, string password, ProgressBar pbar, int totalTicks, int sleep)
{
    for (int i = 0; i < totalTicks; i++)
    {
        Task.Delay(sleep).Wait();
        pbar.Tick(); 
    }
    using (var sftp = new SftpClient(Host, username, password))
    {
        sftp.Connect();
        string fullpath = RemoteDir + d + "/" + customer;
        var files = sftp.ListDirectory(fullpath);
        foreach (var file in files)
        {
            SftpFileAttributes att = sftp.GetAttributes(fullpath + "/" + file.Name);
            var fileSize = att.Size;
            var ms = new MemoryStream();
            IAsyncResult asyncr = sftp.BeginDownloadFile(fullpath + "/" + file.Name, ms);
            SftpDownloadAsyncResult sftpAsyncr = (SftpDownloadAsyncResult)asyncr;
            int lastpct = 0;
            while (!sftpAsyncr.IsCompleted)
            {
                int pct = (int)((long)sftpAsyncr.DownloadedBytes / fileSize) * 100;
                if (pct > lastpct)
                    for (int i = 1; i < pct - lastpct; i++)
                        pbar.Tick();
            }
            sftp.EndDownloadFile(asyncr);
            string localFilePath = "C:\\" + file.Name;
            var fs = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
            ms.WriteTo(fs);
            fs.Close();
            ms.Close();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

由于我认为没有其他人可以帮助您:看着那个包装看起来很漂亮,但是只是为了证明它仍然可以工作,这不是过分的杀伤力吗?现在,我可能还不是100%,但是您要做的是使用线程。这意味着您可以同时运行两个进程。一个线程将每秒钟左右更新一次控制台,而另一个线程将下载SFTP文件。一旦STFP文件下载完成,更新线程将被杀死。

如果您想显示状态,那么在不知道代码确切细节的情况下,我不能真正建议您,但是您可以检查Filestream的位置以获取总数的百分比。

状态线程将使用类似于以下内容的方式每秒更新一次:

public void foo()
{
    Task.Delay(1000).ContinueWith(t=> bar());
}

public void bar()
{
    // do stuff like check that the FileStream position has moved and change the console text
}

除此之外,还有很多事情要做,我不会为您编写所有代码,但希望可以为您指明一个方向(可能不是最好的方向)。