簡體   English   中英

WPF在異步文件復制過程中顯示進度欄

[英]WPF Showing progress bar during async file copy

我是wpf newb,所以這個問題可能很簡單。 我正在嘗試將文件從一個文件夾復制到另一個文件夾。 我想在復制過程中顯示進度條。

我的代碼是這樣的:

if (!System.IO.File.Exists(basemapDest))
{
    await Copier.CopyFiles(new Dictionary<string, string>
    {
        {basemapSrc, basemapDest},
    }, prog => prgBaseMap.Value = prog);
}

public static class Copier
{
    public static async Task CopyFiles(Dictionary<string, string> files, Action<int> progressCallback)
    {
        for (var x = 0; x < files.Count; x++)
        {
            var item = files.ElementAt(x);
            var from = item.Key;
            var to = item.Value;

            using (var outStream = new FileStream(to, FileMode.Create, FileAccess.Write, FileShare.Read))
            {
                using (var inStream = new FileStream(from, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    long fileLength = from.Length;
                    await inStream.CopyToAsync(outStream);
                }
            }

            progressCallback((int)((x + 1) / files.Count) * 100);
        }
    }
}

我的XAML代碼:

<StackPanel>
    <ProgressBar x:Name="prgBaseMap" Height="10" Visibility="Collapsed"/>
</StackPanel>

雖然此功能可用於報告文件已被復制,但在執行復制時不會顯示進度。 我究竟做錯了什么 ?

***編輯,這不是帶有進度條報告stream.copyto的副本

所引用的問題使用的是BackgroundWorker,如今,許多人認為它已經過時了。 這個問題是關於使用新的.NET異步模型的。 我希望所提供的解決方案對其他人也有用。

這是一個解決方案,可讓您在復制文件時顯示進度:

public static class Copier
{
    public static async Task CopyFiles(Dictionary<string, string> files, Action<double> progressCallback)
    {
        long total_size = files.Keys.Select(x => new FileInfo(x).Length).Sum();

        long total_read = 0;

        double progress_size = 10000.0;

        foreach(var item in files)
        {
            long total_read_for_file = 0;

            var from = item.Key;
            var to = item.Value;

            using (var outStream = new FileStream(to, FileMode.Create, FileAccess.Write, FileShare.Read))
            {
                using (var inStream = new FileStream(from, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    await CopyStream(inStream , outStream, x =>
                    {
                        total_read_for_file = x;
                        progressCallback(((total_read + total_read_for_file)/ (double)total_size) * progress_size);
                    } );
                }
            }

            total_read += total_read_for_file;
        }
    }

    public static async Task CopyStream(Stream from, Stream to, Action<long> progress)
    {
        int buffer_size = 10240;

        byte[] buffer = new byte[buffer_size];

        long total_read = 0;

        while (total_read < from.Length)
        {
            int read = await from.ReadAsync(buffer, 0, buffer_size);

            await to.WriteAsync(buffer, 0, read);

            total_read += read;

            progress(total_read);
        }
    }

}

您可以像這樣使用它:

var dictionary = new Dictionary<string, string>
{
    {"c:\\source_file1.dat", "c:\\destination_file1.dat"},
    {"c:\\source_file2.dat", "c:\\destination_file2.dat"},
};

prgBaseMap.Maximum = 10000.0;

await Copier.CopyFiles(dictionary, prog => prgBaseMap.Value = prog);

此解決方案通過一次手動復制10k字節的文件內容來工作( CopyStream方法)。 並且每次更新進度條。

首先,它將求和源文件的總長度,以便能夠計算相對進度。

CopyFiles方法將通過調用相對於10000.0的進度來向調用方報告進度。 這就是進度條最多需要達到10000.0的原因。

可以使用輸入文件的長度總和代替使用10000.0的雙10000.0值。 這樣,您還可以報告已復制字節的總數。

在這種情況下,您將必須計算調用方的長度總和。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM