71 / 62 / 33
Регистрация: 03.09.2013
Сообщений: 306
1

BackgroundWorker блокирует главный поток

13.03.2014, 17:06. Показов 1848. Ответов 2
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Подскажите как поправить. Код копирует файлы отмеченные галочками в ListView, увеличивает значение прогресс бара и добавляет имя в текст бокс. Прогресс бар работает неплохо, текст бокс обновляется но с запозданием, и главная форма "не отвечает" во время копирования.
Не совсем понимаю работу делегатов, буду рад если подскажете.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
 
            this.Invoke((MethodInvoker)delegate
                           {
                               progressBar1.Value = 0;
            double cou = 100 / listView1.CheckedItems.Count;
 
            foreach (ListViewItem c in listView1.CheckedItems)
            {
                if (c.Checked)
                {
                    string curfile = c.SubItems[0].Text;
                    string curpath = c.SubItems[1].Text;
                    string distpach = c.SubItems[2].Text;
 
 
                    
 
                    if (c.SubItems[3].Text == "False") 
                    {
                        try
                        {
                            if (!Directory.Exists(distpach)) 
                            {
                                Directory.CreateDirectory(distpach);
                            
                            }
                            File.Move(Path.Combine(curpath, curfile), Path.Combine(distpach, curfile));
                            richTextBox1.AppendText("переещйн файл из " + c.Name + " в " + distpach);
                        }
                        catch (IOException ex)
                        {
                            MessageBox.Show("Файл " + c.Name + " не перемещён" + Environment.NewLine + ex.Message);
                        }
                    }
                   
                
                }
                
                               progressBar1.Value = progressBar1.Value + (int)(cou* 1.0f);
                
            }
            });
        }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.03.2014, 17:06
Ответы с готовыми решениями:

Главный поток и вторичный
1. При нажатии на кнопку Start в новом потоке запускается server.AcceptTcpClient() (который...

Не могу остановить поток BackgroundWorker
При нажатии кнопки отмена выполняющийся поиск в BackgroundWorker-е должен остановится, но что то не...

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

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

2
Эксперт .NET
17790 / 12941 / 3381
Регистрация: 17.09.2011
Сообщений: 21,215
13.03.2014, 18:46 2
Цитата Сообщение от Driwars Посмотреть сообщение
this.Invoke
Эта строчка перенаправляет указанный аргументом делегат в родительский поток формы.
Фактически, вся работа выполняется в основном потоке, потому и зависания.

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

Но если вам нужно делегировать только обращение к контролам, то зачем перенаправлять всю работу в основной поток?
Вызывайте Invoke только на тех строчках, в которых происходит обращение к элементам управления.
Ну а если уж вы используете BackgroundWorker (судя по сигнатуре метода), то и вообще забудьте про Invoke и используйте метод ReportProgress — он сам отмаршаллит куда надо.
1
71 / 62 / 33
Регистрация: 03.09.2013
Сообщений: 306
13.03.2014, 20:12  [ТС] 3
kolorotur,
Спасибо.
Насколько я понимаю его можно использовать так
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
}
                
                               progress= progress +(int)(cou* 1.0f);
                               
                               backgroundWorker1.ReportProgress(progress, "Working...");
            }
            backgroundWorker1.ReportProgress(100, "Complete!");
 
 
 
 private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }
Проблема не только в отправке в основной поток данных о прогрессе, но и получение из ListView значений это тоже требует делегата. Поэтому всему циклу foreach приходится делать Invoke.
Как нибудь разделить можно? Работать с программой во время выполнения не надо, но по крайней мере надо чтоб её можно было таскать и сворачивать в трей.
Может есть смысл перед копированием файлов занести данные из ListView в массивы, и освободить контрол? Думаю инициализация массива пройдёт почти без задержки.
0
13.03.2014, 20:12
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.03.2014, 20:12
Помогаю со студенческими работами здесь

Как передать данные из дочерного потока в главный поток
Здравствуйте. Искал по форуму есть похожие темы но нет решения. Есть класс который загружает данные...

Определить, что блокирует поток
Есть приложение на WinForms, и какой-то код блокирует основной поток. Нужно найти этот самый...

Как реализовать, чтобы главный поток ждал, пока завершат свою роботу другие потоки
Всем доброго времени суток. Есть следующий код, как реализовать чтоб главный поток подождал пока...

WebClient.DownloadDataAsync блокирует вызывающий поток
есть код private void CheckForUpdate() { using (WebClient client = new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru