С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
5 / 5 / 3
Регистрация: 04.06.2015
Сообщений: 33
1

Единый блок кода для всех потоков

07.02.2016, 15:39. Показов 1247. Ответов 3
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Как выполнить блок кода для всех потоков 1 раз, а не чтобы каждый поток его выполнял.
Вот, по сути урезанная моя программка.
Более детально описал проблему ниже.

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
using System;
using System.Threading;
using System.Windows.Forms;
 
namespace WindowsFormsApplication17
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public object obj = new object();
        private void btnStart_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 3; i++)
            {
                Thread Potok = new Thread(Work);
                Potok.IsBackground = true;
                Potok.Start();
            }
        }
        public void Work()
        {
            while (true)
            {
                if (_png > 0)
                {
                    // Метод Work конвентирует картинки из одного формата в другой.
                }
                else
                {
                    //Блок кода, если в папке закончились картинки.
                    lock (obj) // Чтобы не выскочило 3 MessageBox, но это временное решение, после того как 1 поток продолжит работу, то 2 поток выведет мессадж бокс, а потом и 3-ий. 
                    {
                        MessageBox.Show("Выберите папку с картинками"); // когда нажимает ок, поток выполняет проверку заного и продолжает работу
                        // но надо нажимать 3 раза( 3 потока запускаю ) Как сделать чтобы 1 нажатие на MessageBox означало нажатие и на других.
                    }
                }
            }
        }
 
        private void btnLoadFile_Click(object sender, EventArgs e)
        {
            //происходит подсчет картинок в папке и передает переменной _png кол-во.
        }
    }
}
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.02.2016, 15:39
Ответы с готовыми решениями:

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

Единый базовый класс для всех производных
Здравствуйте! У меня есть два класса - базовый (Base) и производный (Child). В начале я создаю...

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

Единый для всех версий Windows (от 5.1 и выше), способ для вкл\выкл сетевого адаптера
Сабж. Нужен способ отключение и включения адаптера который бы работал на всех виндовсах... ...

3
Эксперт .NETАвтор FAQ
10418 / 5148 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
07.02.2016, 15:55 2
Derevyniy,
1) Нельзя выводить сообщения пользователю в не GUI протоках. Это неправильно как технически, так и архитектурно.
2) Создайте отдельный поток, который будет следить за состоянием потоков (или объекта _png ) и выдавать сообщения пользователю через Invoke.
1
5 / 5 / 3
Регистрация: 04.06.2015
Сообщений: 33
07.02.2016, 20:04  [ТС] 3
Storm23, как только кончаются картинки, я вывожу модальный мессаджбокс для блока потоков и он будет постоянно выводится, пока заного через btnLoadFile не выбрать папку с картинками, после загрузки по нажатию на мессаджбоксе "ок" поток продолжает работу, но надо нажимать 3 раза ибо 3 мессаджа выводится , опять же потому что 3 потока. Как сделать чтобы можно было нажать только 1 раз на 1 мессаджбоксе для продолжения работы всех потоков.

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

Схема приведенная выше работает идеально в 1 потоке. а когда их 2-3 или более, то гемморой с выскакиванием несколько messagebox.

Добавлено через 24 минуты
Попробую максимально описать свою задачу. Выбирается папка с картинками, нажимается кнопка старт,создается ну к примеру 3 потока. Они конвертируют картинки, картинок остается 3, 1 поток забирает картинку, остается 2-е , тут оканчивает конвертирование 2 поток и тоже берет картинку , остается одна. 3 поток долго выполняет операцию и его обгоняет 1 и вновь забирает картинку, остается 0. Выполнил операцию 3 поток и хочет взять картинку, ее нету. Поток идет в else и должен ждать переход останых потоков в else, как 3 потока оказываются в блоке кода else, то выскакивает 1)openfiledialog и просит выбрать новую папку, мы открываем ее и если произошла загрузка картинок, то продолжают работу все 3 потока, если нет, то опять выскакивает openfiledialog и просит выбрать. ИЛИ 2)Выскакивает 1 раз Messagebox с уведомлением что кончились картинки, мол подгрузите новые. Мы нажимаем на btnFileLoad и загружаем картинки, после чего работа всех 3 потоков продолжается.

P.s Storm23, если умел я бы не спрашивал на форуме и не просил помощи. Моих сил и знаний хватило только на это. Да и если я выполню делегат, который в коде GUI выведет messagebox, то ДЛЯ МЕНЯ разницы не будет, ибо будет все точно так же, 3 мессаджбокса, только с технической и архитектурной точки зрения правильно.

Добавлено через 1 час 36 минут
Много букв выше и бреда, поэтому дублирую, думаю смог верно сформулировать.(Моя задача):

Попробую максимально описать свою задачу. Выбирается папка с картинками, нажимается кнопка старт,создается ну к примеру 3 потока. Они конвертируют картинки, картинок остается 3, 1 поток забирает картинку, остается 2-е , тут оканчивает конвертирование 2 поток и тоже берет картинку , остается одна. 3 поток долго выполняет операцию и его обгоняет 1 и вновь забирает картинку, остается 0. Выполнил операцию 3 поток и хочет взять картинку, ее нету. Поток идет в else и должен ждать переход останых потоков в else, как 3 потока оказываются в блоке кода else, то выскакивает 1)openfiledialog и просит выбрать новую папку, мы открываем ее и если произошла загрузка картинок, то продолжают работу все 3 потока, если нет, то опять выскакивает openfiledialog и просит выбрать. ИЛИ 2)Выскакивает 1 раз Messagebox с уведомлением что кончились картинки, мол подгрузите новые. Мы нажимаем на btnFileLoad и загружаем картинки, после чего работа всех 3 потоков продолжается.
0
Эксперт .NETАвтор FAQ
10418 / 5148 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
07.02.2016, 21:22 4
Лучший ответ Сообщение было отмечено Derevyniy как решение

Решение

Цитата Сообщение от Derevyniy Посмотреть сообщение
Попробую максимально описать свою задачу
Спасибо за подробное объяснение задачи. Но я и с первого раза понял что вам нужно
И решение вашей задачи полностью описано в моем посте.
Я вам предлагал создать еще один поток, который будет следить за состоянием других потоков. И как только все они завершат работу - выдать сообщение пользователю.
Вот подробное решение:
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
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
 
namespace WindowsFormsApplication330
{
    public partial class Form1 : Form
    {
        private Button btStart;
        private TaskQueue taskQueue;
 
        public Form1()
        {
            InitializeComponent();
 
            btStart = new Button { Text = "Start", Parent = this };
            btStart.Click += bt_Click;
        }
 
        void bt_Click(object sender, EventArgs e)
        {
            //выбираем папку
            var dlg = new FolderBrowserDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                //блокируем кнопку
                btStart.Enabled = false;
                //запускам поток сканирования директории и поиска картинок
                new Thread(() => FindFiles(dlg.SelectedPath)) { IsBackground = true }.Start();
                //возвращаем управление GUI потоку, что форма не подвисала
                return;
            }
        }
 
        //поток сканирования директории и поиска картинок
        void FindFiles(string path)
        {
            var threads = new List<Thread>();
            taskQueue = new TaskQueue();
 
            //сканируем папку, ищем картинки
            foreach (var file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories))
                switch (Path.GetExtension(file).ToLower())
                {
                    case ".png":
                    case ".bmp":
                    case ".jpg":
                    case ".jpeg":
                        taskQueue.Enqueue(file);//добавляем в очередь задач
                        break;
                }
 
            //запускаем потоки обработки картинок
            for (int i = 0; i < Environment.ProcessorCount - 1; i++)
            {
                var th = new Thread(ProcessFile) { IsBackground = true };
                th.Start();
                //добавляем поток в список потоков
                threads.Add(th);
            }
 
            //ждем завершения всех потоков
            foreach (var t in threads)
                t.Join();
            //все потоки завершены, вызываем метод в GUI потоке
            Invoke((MethodInvoker)OnCompleted);
        }
 
        //поток обработки файлов
        void ProcessFile()
        {
            var file = "";
            while (taskQueue.TryDequeue(out file))//берем очередной файл из очереди
            {
                try
                {
                    using (var bmp = new Bitmap(file))
                    {
                        //обрабатываем файл ...
                        Thread.Sleep(10);
                        //для отладки выводим в консоль
                        Console.WriteLine("Thread id: {0} Prcessed file: {1}", Thread.CurrentThread.ManagedThreadId, Path.GetFileName(file));
                    }
                }
                catch (Exception ex)
                {
                    //не смогли открыть файл
                    Console.WriteLine("Thread id: {0} Error file: {1}", Thread.CurrentThread.ManagedThreadId, Path.GetFileName(file));
                }
            }
        }
 
        //этот метод будет вызван после окончания процесса обработки файлов
        void OnCompleted()
        {
            //включаем кнопку
            btStart.Enabled = true;
            //сообщаем юзеру об окончании процесса
            MessageBox.Show("Completed");
        }
    }
 
    //очередь заданий
    class TaskQueue : ConcurrentQueue<string>
    {
    }
}
Обратите внимание - создается еще один поток, который сначала сканирует директории, формирует очередь заданий. Затем этот же поток запускает потоки обработки. И затем ждет окончания всех этих потоков. После чего вызывает обработчик окончания процесса OnCompleted в контексте GUI потока.
Метод OnCompleted разблокирует кнопку старта, и выдает сообщение об окончании процесса пользователю.
При этом, сообщение выдается только один раз. Кроме того, пока файлы обрабатываются GUI поток свободен, форма не виснет.
1
07.02.2016, 21:22
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.02.2016, 21:22
Помогаю со студенческими работами здесь

Как задать единый размер для всех папок в Windows XP?
Добрый день, дорогие форумчане, у меня есть один вопрос - как задать единый размер для всех папок в...

Как задать единый путь к node_modules для всех проектов
Я использую webpack 2 и все модули подключаются из node_modules в каждом проекте. В документации...

Общение пхп потоков, есть ли область видимая для всех пхп потоков?
Добрый день форумчане. Суть вопроса такова - сайт работает с апи вк, как известно у вк есть...

Является ли метод run() общим для всех потоков?
Есть несколько потоков (экземпляров) одного класса. Что можно сказать про метод run() этого класса,...


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Книги и учебные ресурсы по C#
InfoMaster 08.01.2025
Базовые учебники и руководства Одной из лучших книг для начинающих является "C# 10 и . NET 6 для начинающих" Эндрю Троелсена и Филиппа Джепикса . Книга последовательно раскрывает основные концепции. . .
Что такое NullReferenceEx­­­ception и как исправить?
InfoMaster 08.01.2025
NullReferenceException - одно из самых распространенных исключений, с которым сталкиваются разработчики на C#. Это исключение возникает при попытке обратиться к членам объекта (методам, свойствам или. . .
Что такое Null Pointer Exception (NPE) и как это исправить?
InfoMaster 08.01.2025
Null Pointer Exception (NPE) - это одно из самых распространенных исключений в Java, которое возникает при попытке использовать ссылку на объект, значение которой равно null. Это исключение относится. . .
Русский язык в консоли C++
InfoMaster 08.01.2025
При разработке программ на C++ одной из частых проблем, с которой сталкиваются русскоязычные программисты, является корректное отображение кириллицы в консольных приложениях. Эта проблема особенно. . .
Telegram бот на C#
InfoMaster 08.01.2025
Разработка ботов для Telegram стала неотъемлемой частью современной экосистемы мессенджеров. C# предоставляет мощный и удобный инструментарий для создания разнообразных ботов, от простых. . .
Использование GraphQL в Go (Golang)
InfoMaster 08.01.2025
Go (Golang) является одним из наиболее популярных языков программирования, используемых для создания высокопроизводительных серверных приложений. Его архитектурные особенности и встроенные. . .
Что лучше использовать при создании класса в Java: сеттеры или конструктор?
Alexander-7 08.01.2025
Вопрос подробнее: На вопрос: «Когда одновременно создаются конструктор и сеттеры в классе – это нормально?» куратор уточнил: «Ваш класс может вообще не иметь сеттеров, а только конструктор и геттеры. . .
Как работать с GraphQL на TypeScript
InfoMaster 08.01.2025
Введение в GraphQL и TypeScript В современной разработке веб-приложений GraphQL стал мощным инструментом для создания гибких и эффективных API. В сочетании с TypeScript, эта технология. . .
Счётчик на базе сумматоров + регистров и генератора сигналов согласования.
Hrethgir 07.01.2025
Создан с целью проверки скорости асинхронной логики: ранее описанного сумматора и предополагаемых fast регистров. Регистры созданы на базе ранее описанного, предполагаемого fast триггера. То-есть. . .
Как перейти с Options API на Composition API в Vue.js
BasicMan 06.01.2025
Почему переход на Composition API актуален В мире современной веб-разработки фреймворк Vue. js продолжает эволюционировать, предлагая разработчикам все более совершенные инструменты для создания. . .
Архитектура современных процессоров
inter-admin 06.01.2025
Процессор (центральный процессор, ЦП) является основным вычислительным устройством компьютера, которое выполняет обработку данных и управляет работой всех остальных компонентов системы. Архитектура. . .
История создания реляционной модели баз данных, правила Кодда
Programming 06.01.2025
Предпосылки создания реляционной модели В конце 1960-х годов компьютерная индустрия столкнулась с серьезными проблемами в области управления данными. Существовавшие на тот момент модели данных -. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru