Ahmed Shamel
Ahmed Shamel

Reputation: 1962

Using Progressbar in xamarin fomrs

I have a xamarin form application in which there is option for creating a zip file. I use SharpZipLib.Portable plugin to create the zip file. I used the same sample explained here for creating the zip file. I need to add progress bar to this application. I do this:

double FilesCount=0;
double CopyCount = 0;

    private void CreateZipFile()
    {
        string Folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
        FilesCount = Directory.GetFileSystemEntries(Folder).Count();
        string ZipFilePath = Path.Combine(Folder, "File.zip");
        CreateSample(ZipFilePath, Folder);
    }

    public async void CreateSample(string outPathname, string folderName)
    {

        FileStream fsOut = File.Create(outPathname);
        ZipOutputStream zipStream = new ZipOutputStream(fsOut);

        zipStream.SetLevel(3);

        zipStream.Password = null; 

        int folderOffset = folderName.Length + (folderName.EndsWith("\\") ? 0 : 1);

        CompressFolderAsync(folderName, zipStream, folderOffset);

        zipStream.IsStreamOwner = true;
        zipStream.Close();

        await DisplayAlert("Creating Backup", "Creating backup is completed successfully. The buckup file is store in the following path: " + outPathname, "Ok");

    }

    private void CompressFolderAsync(string path, ZipOutputStream zipStream, int folderOffset)
    {
        string[] files = Directory.GetFiles(path);

        foreach (string filename in files)
        {

            FileInfo fi = new FileInfo(filename);

            string entryName = filename.Substring(folderOffset);
            entryName = ZipEntry.CleanName(entryName);
            ZipEntry newEntry = new ZipEntry(entryName);
            newEntry.DateTime = fi.LastWriteTime;
            newEntry.Size = fi.Length;
            zipStream.PutNextEntry(newEntry);

            byte[] buffer = new byte[4096];
            using (FileStream streamReader = File.OpenRead(filename))
            {
                StreamUtils.Copy(streamReader, zipStream, buffer);
            }
            zipStream.CloseEntry();
        }

        CopyCount += 1;
        CreateBackupProgress.ProgressTo(CopyCount / FilesCount, 800, Easing.Linear);


        string[] folders = Directory.GetDirectories(path);

        foreach (string folder in folders)
        {
            CompressFolderAsync(folder, zipStream, folderOffset);
        }

    }

The problem is that the progress bar doesn't animated until the process finish. I tried to make the method async as follow:

await CreateBackupProgress.ProgressTo(CopyCount / FilesCount, 800, Easing.Linear);

But also not worked. I try using Task.Run() to make method works in background. This is the code:

    private async void CompressFolderAsync(string path, ZipOutputStream zipStream, int folderOffset)
    {
        string[] files = Directory.GetFiles(path);

        await Task.Run(() => {

            foreach (string filename in files)
        {

            FileInfo fi = new FileInfo(filename);

            string entryName = filename.Substring(folderOffset);
            entryName = ZipEntry.CleanName(entryName);
            ZipEntry newEntry = new ZipEntry(entryName);
            newEntry.DateTime = fi.LastWriteTime;
            newEntry.Size = fi.Length;
            zipStream.PutNextEntry(newEntry);

            byte[] buffer = new byte[4096];
            using (FileStream streamReader = File.OpenRead(filename))
            {
                StreamUtils.Copy(streamReader, zipStream, buffer);
            }
            zipStream.CloseEntry();
        }


            CopyCount += 1;

            CreateBackupProgress.ProgressTo(CopyCount / FilesCount, 100, Easing.Linear);

        });

        string[] folders = Directory.GetDirectories(path);

        foreach (string folder in folders)
        {
            CompressFolderAsync(folder, zipStream, folderOffset);
        }

    }

But I get this error:

Unhandled Exception: System.InvalidOperationException: ZipOutputStream was finished occurred

How can I solve this problem?

Upvotes: 1

Views: 458

Answers (1)

Ahmed Shamel
Ahmed Shamel

Reputation: 1962

The problem solved by using this:

double FilesCount = 0;
double CopyCount = 0;

    public async void CreateSample(string outPathname, string folderName)
    {

        FileStream fsOut = File.Create(outPathname);
        ZipOutputStream zipStream = new ZipOutputStream(fsOut);

        zipStream.SetLevel(3);

        zipStream.Password = null;

        int folderOffset = folderName.Length + (folderName.EndsWith("\\") ? 0 : 1);

        CreateBackupProgress.IsVisible = true;

        Task task1 = new Task(CheckProgressbar);
        task1.Start();

        Task task2 = new Task(() => CompressFolderAsync(folderName, zipStream, folderOffset));
        task2.Start();

        await task1;
        await task2;

        zipStream.IsStreamOwner = true;
        zipStream.Close();

        await DisplayAlert("Creating Backup", "Creating backup is completed successfully. The buckup file is store in the following path: " + outPathname, "Ok");

    }

    private void CompressFolderAsync(string path, ZipOutputStream zipStream, int folderOffset)
    {
        string[] files = Directory.GetFiles(path);

        foreach (string filename in files)
        {

            FileInfo fi = new FileInfo(filename);

            string entryName = filename.Substring(folderOffset);
            entryName = ZipEntry.CleanName(entryName);
            ZipEntry newEntry = new ZipEntry(entryName);
            newEntry.DateTime = fi.LastWriteTime;
            newEntry.Size = fi.Length;
            zipStream.PutNextEntry(newEntry);

            byte[] buffer = new byte[4096];
            using (FileStream streamReader = File.OpenRead(filename))
            {
                StreamUtils.Copy(streamReader, zipStream, buffer);
            }
            zipStream.CloseEntry();
        }

        CopyCount += 1;

        string[] folders = Directory.GetDirectories(path);

        foreach (string folder in folders)
        {
            CompressFolderAsync(folder, zipStream, folderOffset);
        }

    }

    private async void CheckProgressbar()
    {

        while (CopyCount != FilesCount)
        {
            await Task.Run(() => { Thread.Sleep(100); }); 
            await CreateBackupProgress.ProgressTo(CopyCount / FilesCount, 100, Easing.Linear);

        }
        await CreateBackupProgress.ProgressTo(1, 100, Easing.Linear);

    }

Upvotes: 3

Related Questions