Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
2 / 2 / 0
Регистрация: 21.11.2013
Сообщений: 65
1
.NET 4.x

Потоки - запуск одновременно с соблюдением порядка присвоения

12.10.2018, 14:17. Показов 1568. Ответов 9

Не подскажите как правильно организовать параллельную загрузку данных. Задача такая: есть текстбокс с вэб адресами (допустим 1000 штук), я беру в цикле первый адрес и запрашиваю HTML код странички, обрабатываю его, как мне надо и отдаю результат обработки в другой текстбокс.
Я хочу добиться параллельности процесса, так как если эти запросы идут один за другим, то все происходит очень медленно и апликация зависает, допустим хочу запустить первую сотню и сразу же 2 сотню и 3 сотню.
Такое возможно? Если да, то как соблюсти, чтобы данные вставали напротив страницы, т.е. к CheckboxAdrersses.Lines[1] примапился бы CheckboxResult.Lines[1], как передать этот порядок в поток, так как через Add они будут присваиваться как попало, то из 1 сотни, то из 2 то из 3, так как все потоки будут работать параллельно
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.10.2018, 14:17
Ответы с готовыми решениями:

Потоки, одновременно 5 задач
Уже 2 тема пошла, но от той я куча информации почитал, но так и не понял, как мне реализовать такой...

Пул потоков и потоки одновременно
Мне интересно безопасно ли использовать пул потоков и обыкновенные потоки одновременно? Например,...

Как запустить потоки одновременно
#include <iostream> #include <windows.h> #include <dos.h> using namespace std; const int m = 2,...

Как заставить работать потоки одновременно
Привет,Я запускаю два потока пуля и самолет но они работают в таком порядке сначала пуля летит до...

9
177 / 151 / 31
Регистрация: 28.09.2018
Сообщений: 204
12.10.2018, 15:58 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
  public partial class MainWindow : Window
    { 
 
        // очередь заданий(Id)
        public static ConcurrentQueue<uint> QueueId = new ConcurrentQueue<uint>();
 
        // очередь готовых результатов
        public static ConcurrentQueue<string> QueueResults = new ConcurrentQueue<string>();
 
        Thread[] workers;
 
        static object _locker = new object();
 
        public MainWindow()
        {
            InitializeComponent();
 
            int workerCount = 50; // кол-во работающих потоков, можно менять прямо на лету
 
 
            // поток контроля очереди
            Thread threadQueueControl = new Thread(QueueControl);
            threadQueueControl.Start();
 
            workers = new Thread[workerCount];
 
            //  запустить требуемое кол-во потоков 
            for (int i = 0; i < workerCount; i++)
            {
                (workers[i] = new Thread(Parser) { IsBackground = true }).Start();
            }
 
 
        }
 
        public void QueueControl()
        {
 
            while (true)
            {
                /*
                if (xxx)// тут проверяем не пора ли остановиться
                {
                    return;
                }
                */
 
                if (QueueId.Count >= 10000) // если в очереди скопилось 10000 заданий, ждём
                {
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                    continue;
                }
 
                if (i < finishId) // если ещё есть задания для добавления в очередь, добавляем
                {
                    QueueId.Enqueue(i);
                    i++;
                }
 
                if (QueueId.Count == 0)
                {
                    Finish = true;
                    return;
                }
            }
        }
 
 
        public void Parser()
        {
           uint id;
            string name;
 
            while (true)
            {
                /*
                if (xxx)// тут проверяем не пора ли остановиться
                {
                    return;
                }
                */
                if (QueueId.Count == 0)
                {
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                    continue;
                }
 
                if (!QueueId.TryDequeue(out id))
                {
                    continue;
                }
 
                lock (_locker)
                {
                    Position = id; // номер последнего задания взятого в обработку
                }
 
                var result = GetResultFromServer(id); // запрос нужных данных с сервера
 
                Interlocked.Increment(ref Ready); // счётчик выполненных заданий 
 
                // если задание провалилось, забиваем на него и едем дальше
                if (result == null) 
                {
                    continue;
                }
 
                QueueResults.Enqueue(id + ": " + result);
 
 
            }
        }
 
    }
2
2 / 2 / 0
Регистрация: 21.11.2013
Сообщений: 65
12.10.2018, 16:12  [ТС] 3
Спасибо конечно, но зачем мне такой огород городить для управления потоками, мне бы чего-нить попроще, типа делим задания по 100 элементов и запускаем все паралельно.
Где в этом коде будет исполняться само задание то что мне нужно? Как мапить результат нужный индекс страницы к нужному индексу результата если они не по порядку будут идти, а параллельно.
0
177 / 151 / 31
Регистрация: 28.09.2018
Сообщений: 204
12.10.2018, 16:41 4
Это код с проекта, который на 90% совпадает с указанной задачей. 50-100 потоков работало без проблем.
Если что-то не нужно, то можно выкинуть.

Цитата Сообщение от withnofear Посмотреть сообщение
де в этом коде будет исполняться само задание то что мне нужно?
вызываем тут:
C#
1
var result = GetResultFromServer(id);
а так, делается метод в котором обрабатываем как угодно всё что нужно. У меня было так:
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
public string GetResultFromServer(uint id)
        {
 
            byte[] htmlData;
            var address = "http://www.somesite.com/" + id;
            var client = new NoKeepAlivesWebClient();
            try
            {
                htmlData = client.DownloadData(address);
            }
            catch (Exception ex)
            {
                return null;
            }
 
            client.Dispose();
 
            var htmlResult = Encoding.UTF8.GetString(htmlData);            
 
            var mat = Regex.Match(htmlResult, "<h3 class=\"hosts_name\">(.*?)</h3>");
            if (!mat.Success)
            {
                return null;
            }
            var result = mat.Groups[1].Value;
            return result;
        }
Добавлено через 6 минут
Цитата Сообщение от withnofear Посмотреть сообщение
Как мапить результат нужный индекс страницы к нужному индексу результата если они не по порядку будут идти, а параллельно
сортировку готовых результатов для отображения на форме в данном случае можно делать прямо в основном потоке, через цикл или по таймеру.
2
Неадекват
1440 / 1191 / 232
Регистрация: 02.04.2010
Сообщений: 2,728
12.10.2018, 17:16 5
withnofear, передавайте вместе с url его номер строки. И по окончании потока возвращайте и вставляйте куда надо.
1
2 / 2 / 0
Регистрация: 21.11.2013
Сообщений: 65
12.10.2018, 21:14  [ТС] 6
А как передавать в поток?
0
Неадекват
1440 / 1191 / 232
Регистрация: 02.04.2010
Сообщений: 2,728
12.10.2018, 21:17 7
Ну ссылку же вы передаете, вот и передавайте вместо нее структуру из ссылки и ее номера.
0
2 / 2 / 0
Регистрация: 21.11.2013
Сообщений: 65
12.10.2018, 22:29  [ТС] 8
Не предаю ссылку, она фиксированная только меняется конец на параметр из текстбокса в цикле:

Например с Яндексом это выглядело бы так:
C#
1
2
        string addressTemplate = "https://yandex.ru/search/?lr=10398&text=%GROUPNAME%";
        string downloadString = client.DownloadString(addressTemplate.Replace("%GROUPNAME%", textBoxGroups.Lines[a]));
0
Неадекват
1440 / 1191 / 232
Регистрация: 02.04.2010
Сообщений: 2,728
13.10.2018, 00:12 9
Цитата Сообщение от withnofear Посмотреть сообщение
Не предаю ссылку, она фиксированная только меняется конец на параметр из текстбокса в цикле:


PS: Я думаю вам следует немного подучить ООП. Без него ваш код на шарпе будет несколько... странным.
0
2 / 2 / 0
Регистрация: 21.11.2013
Сообщений: 65
13.10.2018, 14:20  [ТС] 10
Дык этим и занимаюсь, делаю задачу и по ходу учу, если бы я все знал не сидел бы тут.

Добавлено через 47 секунд
И насколько я понял в поток только тип Data можно передавать, с этим тоже проблемы...
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.10.2018, 14:20

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

Как заставить потоки работать одновременно?
Для ядра Linux 2.6.18 или новее написать модуль, который будет делать следующее: 1. Сформировать...

Проигрывание 2 или более звуков одновременно (Потоки)
Не забываем и помним что музыка проигрывается из ресурсов. Имеется 2 потока. static void...

Как одновременно воспроизвести аудио-потоки от разных участников чата?
Пишу аудио-чат конференцию. Передаю аудио-поток с микрофона клиента на сервер, с сервера...

Правильно создать пул потоков, запустить эти потоки одновременно и дождаться их завершения
Добрый день! Подскажите пожалуйста, как правильно создать пул потоков, запустить эти потоки...


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

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

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