Nano Hash - криптовалюты, майнинг, программирование

Распаковать файл с активным индикатором выполнения С#

Я пытаюсь создать собственный установщик для извлечения zip-файла из фиксированного местоположения в предпочтительное для пользователей местоположение, которое я посетил и нашел много источников, все из которых не работают. Проблема с тем, что приложение зависает при распаковке пакета и не обновляет индикатор выполнения до его 100% завершения (на мой взгляд, не очень полезно)

Это то, что у меня есть до сих пор

void Install()
{
      using (Ionic.Zip.ZipFile zip = Ionic.Zip.ZipFile.Read(Constants.UpdateZipPath))
      {
            zip.ExtractProgress += new EventHandler<ExtractProgressEventArgs>(Zip_ExtractProgress);
            zip.ExtractAll(installDir, ExtractExistingFileAction.OverwriteSilently);
      }
}

void Zip_ExtractProgress(object sender, ExtractProgressEventArgs e)
{
      if (e.TotalBytesToTransfer > 0)
      {
            ProgressBar.Value = Convert.ToInt32(100 * e.BytesTransferred / e.TotalBytesToTransfer);
      }
}

Это один из источников, который я нашел, и он не работает С отчетом о проделанной работе

Когда я пытаюсь использовать Task.Factory.StartNew(() => Install());, я получаю эту ошибку

Exception thrown: 'System.InvalidOperationException' in WindowsBase.dll
Exception thrown: 'System.InvalidOperationException' in DotNetZip.dll

Я использую Ionic.Zip.ZipFile, и когда я использую его вне основного потока, он не работает.

14.09.2020

Ответы:


1

Вы не должны обновлять значение ProgressBar напрямую, если только ваш код не работает в основном потоке.

Следующие методы расширения вызовите необходимые вспомогательные процедуры, чтобы обойти это ограничение:

public static class ProgressBarExtensions
{
    //  this extension method can be used for any Control which supports
    //  InvokeRequired() and BeginInvoke()
    public static void EnsureInvokeAsync(this Control control, Action action)
    {
        if (control.InvokeRequired)
        {
            control.BeginInvoke(action);
        }
        else
        {
            action();
        }
    }

    public static void SetProgressValue(this ProgressBar progressBar, int progressValue)
    {
        // https://stackoverflow.com/a/21969844/1911064
        // the lambda will capture the argument in a closure
        // the compiler does all the hard work for you
        progressBar.EnsureInvokeAsync(() => progressBar.Value = progressValue);
    }
}

Пример вызова:

progressBar1.SetProgressValue(myValue);
14.09.2020
  • Так близко, это приложение wpf, но по какой-то причине ProgressBar — это система, управляющая индикатором выполнения! <ProgressBar Margin="0,20,0,0" Height="20" x:Name="ProgressBar0" Visibility="Hidden"></ProgressBar> 15.09.2020

  • 2

    Я заставил его работать с тем, что было у Axel Kemper, но мне пришлось запустить поток непосредственно перед тем, как я начал распаковывать, вот код, который я придумал!

    public class MyClass
    {
        public bool InstallIsCompleted = false;
        public string CurrentFileBeingExtracted = "";
        public int TotalNumberOfFiles = 1;
        public int NumberOfFilesTransferred = 1;
    
        public void MyFunction()
        {
            new Thread(Update).Start();
            Task.Factory.StartNew(() => Install());
        }
    
        void Update()
        {
            while (!InstallIsCompleted)
            {
                Dispatcher.Invoke(() =>
                {
                    // updates UI text elements including the display for which file
                    // is being extracted and the total progress of the total extraction
                    DisplayCurrentFile.Text = CurrentFileBeingExtracted;
                    float Percentage = (NumberOfFilesTransferred*100) / TotalNumberOfFiles;
                    InstallationProgressBar.Value = Percentage + (SecondProgressBar.Value * (1 / TotalNumberOfFiles));
                });
            }
            //Install Completed
            /* other code here */
        }
    
        void Install(string ZipPath, string TargetPath)
        {
            using (ZipFile zip = ZipFile.Read(ZipPath))
            {
                // initial setup before extraction
                TotalNumberOfFiles= zip.Entries.Count;
                zip.ExtractProgress += new EventHandler<ExtractProgressEventArgs>(Zip_ExtractProgress);
                // actual extraction process
                zip.ExtractAll(TargetPath, ExtractExistingFileAction.OverwriteSilently);
                // since the boolean below is in the same "thread" the extraction must 
                // complete for the boolean to be set to true
                InstallIsCompleted = true;
            }
        }
    
        void Zip_ExtractProgress(object sender, ExtractProgressEventArgs e)
        {
            // must be above 0 to prevent *divide by 0 error
            if (e.TotalBytesToTransfer > 0)
            {
                // If file has completed transfer, update the number of files transferred
                if (Convert.ToInt32(100 * e.BytesTransferred / e.TotalBytesToTransfer) >= 100)
                {
                    NumberOfFilesTransferred++;
                }
                // updates the current file being exracted
                CurrentFileBeingExtracted = e.CurrentEntry.FileName.Replace("zip::", "");
                // updates the progress
                ProgressBarExtensions.SetProgressValue(InstallationProgressBar, Convert.ToInt32(100 * e.BytesTransferred / e.TotalBytesToTransfer));
            }
        }
    }
    
    
    public static class ProgressBarExtensions
    {
            //  this extension method can be used for any Control which supports
            //  InvokeRequired() and BeginInvoke()
            public static void EnsureInvokeAsync(this Control control, Action action)
            {
                if (control.InvokeRequired)
                {
                    control.BeginInvoke(action);
                }
                else
                {
                    action();
                }
            }
    
            public static void SetProgressValue(this ProgressBar progressBar, int progressValue)
            {
                // https://stackoverflow.com/a/21969844/1911064
                // the lambda will capture the argument in a closure
                // the compiler does all the hard work for you
                progressBar.EnsureInvokeAsync(() => progressBar.Value = progressValue);
            }
        }
    
    

    Это сработало на 100%, как я и хотел, хотя расчет прогресса не является точным на 100%, поскольку он равномерно делит общий размер на количество файлов, поэтому файл размером 10 КБ из zip-архива размером 1 МБ может составлять 25% завершения. если только 4 файла.

    По какой-то причине e.TotalBytesToTransfer учитывает только каждый файл, и я не уверен, что есть надежный способ рассчитать размер извлечения перед извлечением, поэтому в этом случае возможно только получить ход извлечения для каждого файла и вычислить, сколько там файлов находятся

    16.09.2020
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..