Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
81 / 75 / 29
Регистрация: 08.08.2013
Сообщений: 410
Записей в блоге: 1
1

Ошибка в многопоточной программе

19.12.2016, 14:22. Просмотров 1054. Ответов 4
Метки нет (Все метки)

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

И все вроде работает.
Я нажимаю на кнопку, которая запускает данную задачу, задача выполняется, список файлов печатается, секундомер отобразил потраченное время. Но при повторном многократном нажатии на данную кнопку иногда вылетает ошибка.

C#
1
"Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления 'label1' не из того потока, в котором он был создан."
Иногда она вылетает после 8 нажатия на кнопку, иногда после 20, иногда после первого, иногда вообще это исключение не появляется (нажатие более 40 раз).

Прошу подсказать, из-за чего такое может быть:

Во вложении сам проект:

Кликните здесь для просмотра всего текста
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
namespace MyExp
{
    public partial class Form1 : Form
    {
        int i; //подсчет количества запусков программы
        string path;
        MyClass ob_MyClass;  //класс, в котором содержится метод поиска папок, сделан для многопоточности
        MyLib_Sekundomer ob_sekundomer; //класс секундомер
 
 
        public Form1()
        {
            InitializeComponent();
            textBox1.Text = @"C:\_TEMP";
            label2.Text = "попытка № 0";
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            textBox2.Clear();
            label2.Text = "попытка № "+(++i).ToString();
            path = textBox1.Text;
 
            ob_sekundomer = new MyLib_Sekundomer(SynchronizationContext.Current);
            ob_sekundomer.EventChangeTime += metod_PrintTime; //
 
            ob_MyClass = new MyClass(path);
            ob_MyClass.EndWork += Print_rez;
 
            Thread t1 = new Thread(ob_MyClass.metod1);
            t1.IsBackground = true;
            t1.Start();
 
            ob_sekundomer.Start(); 
 
            textBox2.AppendText("начало работы" + "\n");
 
        }
 
        void Print_rez()
        {
            Action action = () =>
            {
                foreach (string s in ob_MyClass.folders)
                {
                    textBox2.AppendText(s + "\n");
                    
                }
                button1.Enabled = true;
            };
            Invoke(action);
 
            ob_sekundomer.Stop();
 
            
 
        }
 
 
        void metod_PrintTime()
        {
            label1.Text = ob_sekundomer.ts.ToString(@"hh\:mm\:ss\:ff");
        }
 
    }
 
 
    class MyClass
    {
        private string path;
        public List<string> folders;
         
 
        public event Action EndWork;
 
 
        public MyClass(string path)
        {
            this.path = path;
        }
 
 
        public void metod1()
        {
            
            MyLib_File ob = new MyLib_File(path, SearchOption.AllDirectories);  //класс, который создает список папок, даже в том случае, если к какой нибудь папке нет доступа
            folders = ob.rezdirs;
            EndWork();
        }
    }
 
 
 
    
}
 
 
 
 
namespace MyExp
{
    class MyLib_File
    {
        string path;
        SearchOption searchOption;
        public List<string> rezdirs;
        public List<string> rezdirs_error;
 
        public MyLib_File(string path, SearchOption searchOption)
        {
            this.path = path;
            this.searchOption = searchOption;
            rezdirs = new List<string>();
            rezdirs_error = new List<string>();
 
            GetFolders();
        }
 
 
        public List<string> GetFolders() //метод
        {
            Stack<string> dirs = new Stack<string>();
            string[] subDirs;
            dirs.Push(path);
 
            while (dirs.Count > 0)
            {
                string currentDirPath = dirs.Pop();
                if (searchOption == SearchOption.AllDirectories)
                {
                    try
                    {
                        subDirs = new string[0];
                        subDirs = Directory.GetDirectories(currentDirPath);
                        foreach (string subDirPath in subDirs)
                        {
                            dirs.Push(subDirPath);
                            rezdirs.Add(subDirPath);
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        rezdirs_error.Add(currentDirPath);
                        continue;
                    }
                    catch (DirectoryNotFoundException)
                    {
                        rezdirs_error.Add(currentDirPath);
                        continue;
                    }
                }
 
 
            }
 
            return rezdirs;
        }
 
        public List<string> GetFiles() //метод 
        {
            List<string> files = new List<string>();
            try
            {
                files.AddRange(Directory.GetFiles(path));
            }
            catch
            {
 
            } files.Add("нет доступа к папке");
 
            return files;
 
        }
 
 
 
    }
 
 
 
 
    class MyLib_Sekundomer
    {
        SynchronizationContext _context;
 
        System.Timers.Timer MyTimer;
 
 
        public TimeSpan ts;
 
        public event Action EventChangeTime;
 
 
 
        public MyLib_Sekundomer(SynchronizationContext _context)
        {
            this._context = _context;
 
            ts = new TimeSpan(0, 0, 0, 0, 0);
 
            MyTimer = new System.Timers.Timer(10);
            MyTimer.Elapsed += metod1_SekundomerStart;
 
        }
 
 
        public void Start()
        {
            if (MyTimer.Enabled == false)
            {
                MyTimer.Start();
            }
            else
            {
                MyTimer.Stop();
            }
 
        }
 
        public void Reset()
        {
            ts = new TimeSpan(0, 0, 0, 0, 0);
        }
 
        public void Stop()
        {
            MyTimer.Stop();
        }
 
        private void metod1_SekundomerStart(Object source, System.Timers.ElapsedEventArgs e)
        {
            ts = ts.Add(new TimeSpan(0, 0, 0, 0, 10));
            _context.Send(obertEvent, null);
            EventChangeTime();
        }
 
 
 
        public void EndWork()
        {
            MyTimer.Elapsed -= metod1_SekundomerStart;
            MyTimer.Stop();
            MyTimer.Dispose();
 
        }
 
        public void obertEvent(object n)
        {
            EventChangeTime();
        }
 
 
 
    }
}
0
Вложения
Тип файла: 7z 20-файлы Рё таймер (exp).7z (32.2 Кб, 2 просмотров)
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.12.2016, 14:22
Ответы с готовыми решениями:

Метод For в многопоточной программе
Почему данный код не компилируется и как исправить ошибку? using System; using...

Одновременный инкремент в многопоточной программе
Подпрограмма выполняется в многопоточном режиме. i, j - глобальные переменные. Каждый поток...

Назначение параметров в многопоточной программе
Ребят от чего зависит вот эти параметры в моей программе? Mythread t1 = new...

Умножение матриц в многопоточной программе
class Program { static int value = 50; static void Main(string args) ...

4
81 / 75 / 29
Регистрация: 08.08.2013
Сообщений: 410
Записей в блоге: 1
19.12.2016, 14:26  [ТС] 2
Кликните здесь для просмотра всего текста
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
namespace MyExp
{
    public partial class Form1 : Form
    {
        int i; //подсчет количества запусков программы
        string path;
        MyClass ob_MyClass;  //класс, в котором содержится метод поиска папок, сделан для многопоточности
        MyLib_Sekundomer ob_sekundomer; //класс секундомер
 
 
        public Form1()
        {
            InitializeComponent();
            textBox1.Text = @"C:\_TEMP";
            label2.Text = "попытка № 0";
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            textBox2.Clear();
            label2.Text = "попытка № "+(++i).ToString();
            path = textBox1.Text;
 
            ob_sekundomer = new MyLib_Sekundomer(SynchronizationContext.Current);
            ob_sekundomer.EventChangeTime += metod_PrintTime; //
 
            ob_MyClass = new MyClass(path);
            ob_MyClass.EndWork += Print_rez;
 
            Thread t1 = new Thread(ob_MyClass.metod1);
            t1.IsBackground = true;
            t1.Start();
 
            ob_sekundomer.Start(); 
 
            textBox2.AppendText("начало работы" + "\n");
 
        }
 
        void Print_rez()
        {
            Action action = () =>
            {
                foreach (string s in ob_MyClass.folders)
                {
                    textBox2.AppendText(s + "\n");
                    
                }
                button1.Enabled = true;
            };
            Invoke(action);
 
            ob_sekundomer.Stop();
 
            
 
        }
 
 
        void metod_PrintTime()
        {
            label1.Text = ob_sekundomer.ts.ToString(@"hh\:mm\:ss\:ff");
        }
 
    }
 
 
    class MyClass
    {
        private string path;
        public List<string> folders;
         
 
        public event Action EndWork;
 
 
        public MyClass(string path)
        {
            this.path = path;
        }
 
 
        public void metod1()
        {
            
            MyLib_File ob = new MyLib_File(path, SearchOption.AllDirectories);  //класс, который создает список папок, даже в том случае, если к какой нибудь папке нет доступа
            folders = ob.rezdirs;
            EndWork();
        }
    }
 
 
 
    
}
 
 
 
 
namespace MyExp
{
    class MyLib_File
    {
        string path;
        SearchOption searchOption;
        public List<string> rezdirs;
        public List<string> rezdirs_error;
 
        public MyLib_File(string path, SearchOption searchOption)
        {
            this.path = path;
            this.searchOption = searchOption;
            rezdirs = new List<string>();
            rezdirs_error = new List<string>();
 
            GetFolders();
        }
 
 
        public List<string> GetFolders() //метод
        {
            Stack<string> dirs = new Stack<string>();
            string[] subDirs;
            dirs.Push(path);
 
            while (dirs.Count > 0)
            {
                string currentDirPath = dirs.Pop();
                if (searchOption == SearchOption.AllDirectories)
                {
                    try
                    {
                        subDirs = new string[0];
                        subDirs = Directory.GetDirectories(currentDirPath);
                        foreach (string subDirPath in subDirs)
                        {
                            dirs.Push(subDirPath);
                            rezdirs.Add(subDirPath);
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        rezdirs_error.Add(currentDirPath);
                        continue;
                    }
                    catch (DirectoryNotFoundException)
                    {
                        rezdirs_error.Add(currentDirPath);
                        continue;
                    }
                }
 
 
            }
 
            return rezdirs;
        }
 
        public List<string> GetFiles() //метод 
        {
            List<string> files = new List<string>();
            try
            {
                files.AddRange(Directory.GetFiles(path));
            }
            catch
            {
 
            } files.Add("нет доступа к папке");
 
            return files;
 
        }
 
 
 
    }
 
 
 
 
    class MyLib_Sekundomer
    {
        SynchronizationContext _context;
 
        System.Timers.Timer MyTimer;
 
 
        public TimeSpan ts;
 
        public event Action EventChangeTime;
 
 
 
        public MyLib_Sekundomer(SynchronizationContext _context)
        {
            this._context = _context;
 
            ts = new TimeSpan(0, 0, 0, 0, 0);
 
            MyTimer = new System.Timers.Timer(10);
            MyTimer.Elapsed += metod1_SekundomerStart;
 
        }
 
 
        public void Start()
        {
            if (MyTimer.Enabled == false)
            {
                MyTimer.Start();
            }
            else
            {
                MyTimer.Stop();
            }
 
        }
 
        public void Reset()
        {
            ts = new TimeSpan(0, 0, 0, 0, 0);
        }
 
        public void Stop()
        {
            MyTimer.Stop();
        }
 
        private void metod1_SekundomerStart(Object source, System.Timers.ElapsedEventArgs e)
        {
            ts = ts.Add(new TimeSpan(0, 0, 0, 0, 10));
            _context.Send(obertEvent, null);
            EventChangeTime();
        }
 
 
 
        public void EndWork()
        {
            MyTimer.Elapsed -= metod1_SekundomerStart;
            MyTimer.Stop();
            MyTimer.Dispose();
 
        }
 
        public void obertEvent(object n)
        {
            EventChangeTime();
        }
 
 
 
    }
}
0
Вложения
Тип файла: 7z 20-файлы и таймер (exp).7z (32.2 Кб, 2 просмотров)
81 / 75 / 29
Регистрация: 08.08.2013
Сообщений: 410
Записей в блоге: 1
19.12.2016, 14:27  [ТС] 3
ошибка
0
Миниатюры
Ошибка в многопоточной программе  
896 / 652 / 318
Регистрация: 23.10.2016
Сообщений: 1,537
19.12.2016, 15:08 4
Лучший ответ Сообщение было отмечено sysrepos как решение

Решение

235 строка - вызов делегата без использования контекста синхронизации. Эту строку нужно удалить, так как корректный вызов производится в 234 строке.
1
81 / 75 / 29
Регистрация: 08.08.2013
Сообщений: 410
Записей в блоге: 1
19.12.2016, 15:15  [ТС] 5
спасибо!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.12.2016, 15:15

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Функция с fprintf в многопоточной программе
Насколько я знаю, fprintf не многопоточен. Т.е. я не могу просто взять и использовать fprintf() в...

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

Устранение узкого места в многопоточной программе
Доброго времени суток, столкнулся с узким местом при разработке много поточной программы на питоне....

Медленная работа и ловля исключений в многопоточной программе
Здравствуйте. Сразу хочу предупредить, что это мой первый проект поэтому судите строго, но не...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.