Почему WinForm застревает с BackgroundWorker? - PullRequest
0 голосов
/ 11 марта 2019

Привет, ребята, я пытался скопировать некоторые файлы с этим кодом, все хорошо, и приложение будет копировать файлы, но в процессе копирования я не могу переместить свое приложение или сделать что-либо, что я пытался использовать поток, но это не работает, я также использую backgroundWorker, но все женичто, единственный элемент управления, который не застревает, является progressBar, его отлично работает вот мой код:

 public Form1()
    {
        InitializeComponent();
        backgroundWorker1.Dispose();
        backgroundWorker1.DoWork += BackgroundWorker_DoWork;
        backgroundWorker1.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
        backgroundWorker1.ProgressChanged += BackgroundWorker_ProgressChanged;
        backgroundWorker1.WorkerReportsProgress = true;

        backgroundWorker2.DoWork += BackgroundWorker2_DoWork;
        backgroundWorker2.WorkerReportsProgress = true;
    }

    private void BackgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
    {
        File.Copy(sourcePath, targetPath);
    }

    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < fileSize; i++)
        {
            int p = (i + 1) * 100 / Convert.ToInt32(fileSize);
            backgroundWorker1.ReportProgress(p);
        }
    }

    private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

    }

    private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        lbProgress.Text = e.ProgressPercentage.ToString();
        progressBar1.Value = e.ProgressPercentage;
    }

    private void btnTarget_Click(object sender, EventArgs e)
    {
        folderBrowser = new FolderBrowserDialog();
        if (folderBrowser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            targetPath += folderBrowser.SelectedPath + @"\" + fileName;
            lbTarget.Text = targetPath;
        }
    }

    private void btnSource_Click(object sender, EventArgs e)
    {
        op = new OpenFileDialog();
        if (op.ShowDialog() == DialogResult.OK)
        {
            sourcePath += op.FileName;
            lbSource.Text = sourcePath;
            fileInfo = new FileInfo(sourcePath);
            fileSize = fileInfo.Length / 1024;
            fileName = fileInfo.Name;
            MessageBox.Show(string.Format("File size is: {0} KB", fileSize));
        }
    }

    private void btnCopy_Click(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
        backgroundWorker2.RunWorkerAsync();
    }

Ответы [ 3 ]

3 голосов
/ 11 марта 2019

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

Удалите backgroundWorker1, все равно ничего полезного не происходит.Если у вас нет способа отследить прогресс (чего у вас нет с File.Copy), просто используйте индикатор выполнения без прогресса (установите Стиль в Marquee).

0 голосов
/ 11 марта 2019

Не могли бы вы попытаться обновить DoWork следующим образом:

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int mainProgress = 0;
    for (int i = 0; i < fileSize; i++)
    {
        int calculatedProgress = (i + 1) * 100 / Convert.ToInt32(fileSize);
        if(calculatedProgress > mainProgress)
        {
            mainProgress = calculatedProgress;
            backgroundWorker1.ReportProgress(mainProgress);
        }
    }
}

возможно Вы делаете так много обновлений, что просто Window Thread постоянно обновляет только прогресс и не имеет времени что-либо сделатьеще

0 голосов
/ 11 марта 2019

Для тестирования я создал простое приложение winform с кнопкой, меткой и фоновым рабочим и добавил следующие соответствующие события:

private void OnBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
    var worker = (BackgroundWorker)sender;

    for (int i = 0; i < 10; i++)
    {
        Thread.Sleep(500);
        worker.ReportProgress(i * 10);
    }
}

private void OnBackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
    labelProgress.Text = e.ProgressPercentage.ToString();
}

private void OnBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    labelProgress.Text = "Done";
}

private void OnButtonProgressClick(object sender, System.EventArgs e)
{
    backgroundWorker.RunWorkerAsync();
}

Работает как положено.

...