0 / 1 / 0
Регистрация: 06.12.2020
Сообщений: 24
1

Как отследить когда завершатся все 254 или больше, потока и после этого вывести результат их работы на экран

07.12.2020, 12:02. Показов 3613. Ответов 44
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
при создании потока counter++, при завершении потока counter--, параметр counter меняет значение в итоге должно получиться НОЛЬ и тогда выполниться вывод результатов.

вот так я пробовал решить задачку но, часто counter не спускается до нуля, а если раньше времени начать вывод результатов, мой ПК было много раз во время тэстов показывал СИНИЙ ЭКРАН СМЕРТИ

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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using NetTools;
 
namespace Сканер_IP
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public static void Wait(double seconds)
        {
            int ticks = System.Environment.TickCount + (int)Math.Round(seconds * 1000.0);
            while (System.Environment.TickCount < ticks)
            {
                Application.DoEvents();
            }
        }
 
        int counter = 0; // счетчик потоков
 
        List<string> LstIp = new List<string>();
        string[] ipp = { "192.168.1.1", "192.168.1.66", "192.168.1.69"/*, "192.168.1.2", "192.168.1.3", "192.168.1.4", "192.168.1.5"*/ };
        //IPAddressRange.Parse("192.168.1.1-192.168.1.254");
 
        public void Func(string _ip)
        {
            counter++;
 
            try
            { 
                Ping ping = new Ping();
                PingReply reply = ping.Send(_ip.ToString());
                if (reply.Options != null/* && reply.RoundtripTime <= 0.5*/)
                {
                    LstIp.Add(_ip + "    Ping OK" + "\r\n"); //IP
                    Thread.Sleep(1);
                }
                //else
                //    LstIp.Add(_ip + "    >>>> NO <<<<" + "\r\n");
                //Thread.Sleep(1);
                }
            catch (Exception ex)
            { 
                //MessageBox.Show(ex.Message);
            }
 
            counter--;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                LstIp.Clear();
                foreach (var s in IPAddressRange.Parse(textBox1.Text))
                {
                    Thread myThread = new Thread(() => Func(s.ToString()));
                    myThread.IsBackground = true;
                    myThread.Start();
                    //Thread myThread = new Thread(new ParameterizedThreadStart(Func));
                    //myThread.Start(s);
                }
            }
            catch (Exception)
            {
 
 
            }  
 
            listBox1.Items.Add("первый поток завершен");
 
            while (counter > 0)
            {
                Wait(1.0);
                if (counter <= 0)
                    foreach (var s in LstIp)
                    {
                        listBox1.Items.Add(s);
                    }
            }
 
        }
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.12.2020, 12:02
Ответы с готовыми решениями:

Как вывести на экран результат работы программы
Program Frozen; var n:string; begin n:='электростанция'; delete(n,5,4); end. Как вывести на...

Как результат работы программы вывести на экран
Помогите пожалуйста дополнить две програмки(смысл первой програмки в том что даны два массива А и В...

Как вывести результат работы кода на экран? (файловый ввод/вывод)
#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; int main() { FILE *q=fopen(&quot;file1.txt&quot;,&quot;r&quot;); //...

Как вывести на форму результат работы класса — массив после нажатия на кнопку?
Создал класс в форме с сортировкой массива. Создал на форме елементы button и richTextBox....

44
Злой няш
2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881
07.12.2020, 12:36 2
Лучший ответ Сообщение было отмечено newest newbie как решение

Решение

newest newbie, операции ++ и -- не атомарные. Если два потока одновременно, например, отнимут значение, то в итоге может получится -1, а не -2.

https://docs.microsoft.com/en-... ew=net-5.0
https://docs.microsoft.com/en-... s/volatile

Цитата Сообщение от newest newbie Посмотреть сообщение
СИНИЙ ЭКРАН СМЕРТИ
Вирусы, неправильно драйвера стоят, еще чего. В коде нет ничего, чтобы кидало крит системе.
1
626 / 390 / 135
Регистрация: 06.03.2017
Сообщений: 1,455
07.12.2020, 12:38 3
зачем вам столько потоков??? Лучше уже сделать все в один отдельный поток.
0
Пора на C++?
369 / 263 / 99
Регистрация: 10.04.2020
Сообщений: 1,275
07.12.2020, 12:38 4

Не по теме:

Цитата Сообщение от newest newbie Посмотреть сообщение
мой ПК было много раз во время тэстов показывал СИНИЙ ЭКРАН СМЕРТИ

Кликните здесь для просмотра всего текста
Как отследить когда завершатся все 254 или больше, потока и после этого вывести результат их работы на экран
0
0 / 1 / 0
Регистрация: 06.12.2020
Сообщений: 24
07.12.2020, 13:17  [ТС] 5
Цитата Сообщение от Pilarentes Посмотреть сообщение
Лучше уже сделать все в один отдельный поток
в одном отдельном потоке все также быстро делается?
0
626 / 390 / 135
Регистрация: 06.03.2017
Сообщений: 1,455
07.12.2020, 13:23 6
Цитата Сообщение от newest newbie Посмотреть сообщение
в одном отдельном потоке все также быстро делается?
Быстрее, чем создавать 254 потока и ждать их окончания. Создание потока операция не самая дешевая. Я бы разделил все это не более чем на 4 потока.
1
0 / 1 / 0
Регистрация: 06.12.2020
Сообщений: 24
07.12.2020, 13:41  [ТС] 7
Цитата Сообщение от Pilarentes Посмотреть сообщение
Быстрее, чем создавать 254 потока и ждать их окончания
буду проверять
0
Модератор
Эксперт .NET
15040 / 10266 / 2708
Регистрация: 21.04.2018
Сообщений: 30,427
Записей в блоге: 2
07.12.2020, 14:26 8
Цитата Сообщение от newest newbie Посмотреть сообщение
Цитата Сообщение от Pilarentes Посмотреть сообщение
Быстрее, чем создавать 254 потока и ждать их окончания.
буду проверять
В современном C# явное создание потоков (Thread) используется крайне редко.
Для асинхронного исполнения используются задачи (Task).
Часто в сочетании с async/await, чтобы не лагал GUI.

Сильно в логику не вникал и пишу здесь без Студии, но примерно так (без async/await):
C#
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
        public (string ip, bool result) PingIp(object ip)
        {
            var _ip = ip.ToString();
            try
            {
 
                Ping ping = new Ping();
                PingReply reply = ping.Send(_ip.ToString());
                if (reply.Options != null/* && reply.RoundtripTime <= 0.5*/)
                {
                    Thread.Sleep(1);
                    return (_ip, true);
                }
            }
            catch (Exception ex)
            {
            }
            return (_ip, false);
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            List<Task<(string ip, bool result)>> tasks = new List<Task<(string ip, bool result)>>();
            foreach (var s in IPAddressRange.Parse(textBox1.Text))
                tasks.Add(Task<(string ip, bool result)>.Factory.StartNew(PingIp, s));
 
            Task.WaitAll(tasks.ToArray());
 
            LstIp.Clear();
            foreach (var task in tasks)
            {
                LstIp.Add(task.Result.ip + "    Ping " + (task.Result.result ? "OK" : "Faild") + "\r\n");
            }
        }
1
0 / 1 / 0
Регистрация: 06.12.2020
Сообщений: 24
07.12.2020, 19:12  [ТС] 9
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Сильно в логику не вникал и пишу здесь без Студии, но примерно так (без async/await):
программма зависает на долго.
если добавить вывод в listbox1 комп умирает, незнаю с чем это связано.

мой вариант без зависаний выдает результат за пару секунд, спасибо помог I2um1

добавил пару строк
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
        
public void Func(string _ip)
        {
           Interlocked.Increment(ref counter);
 
            try
            {
                Ping ping = new Ping();
                PingReply reply = ping.Send(_ip.ToString());
                if (reply.Options != null/* && reply.RoundtripTime <= 0.5*/)
                {
                    LstIp.Add(_ip + "    Ping OK" + "\r\n"); //IP
                    Thread.Sleep(1);
                }
                //else
                //    LstIp.Add(_ip + "    >>>> NO <<<<" + "\r\n");
                //Thread.Sleep(1);
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
            }
 
           Interlocked.Decrement(ref counter);
        }
0
Модератор
Эксперт .NET
15040 / 10266 / 2708
Регистрация: 21.04.2018
Сообщений: 30,427
Записей в блоге: 2
07.12.2020, 19:51 10
Цитата Сообщение от newest newbie Посмотреть сообщение
программма зависает на долго.
если добавить вывод в listbox1 комп умирает, не знаю с чем это связано.
У вас какой-то непонятный Слип стои - я не знаю для чего и не стал его убирать.
Но он создаётся в каждом цикле и будет значительно подвешивать общее выполнение метода.
А он выполняется в основном потоке и GUI, естественно, будет лагать.

По нормальному надо делать через async/await, но не я не совсем понял логику, поэтому переделывать не стал.

Добавлено через 2 минуты
Цитата Сообщение от newest newbie Посмотреть сообщение
добавил пару строк
Так нельзя делать.
Вы пишите в List<string> LstIp из разных потоков.
А List - это не потокозащищённая коллекция.
Обязательно будут потери данных.

Добавлено через 1 минуту
newest newbie, ответь для чего у вас там стоит слип?
0
958 / 576 / 268
Регистрация: 20.12.2016
Сообщений: 1,506
07.12.2020, 20:28 11
Цитата Сообщение от newest newbie Посмотреть сообщение
Thread.Sleep(1);
хак который позволяет разблокировать основной поток

Добавлено через 5 минут
Цитата Сообщение от newest newbie Посмотреть сообщение
LstIp.Add(_ip + "    Ping OK" + "\r\n"); //IP
нужно заменить на:
C#
1
2
3
4
lock(syncObject)
{
   LstIp.Add(_ip + "    Ping OK" + "\r\n");
}
syncObject - static object syncObject = new object(); // переменная класса
1
Модератор
Эксперт .NET
15040 / 10266 / 2708
Регистрация: 21.04.2018
Сообщений: 30,427
Записей в блоге: 2
07.12.2020, 20:47 12
Попробуйте такой код.
Промежуточный список убран.
Результат пишется сразу в листбокс.
Ожидание исполнения всех задач убрано.
Каждая задача по окончании сама записывает свои результаты в листвох через Invoke.
Так как все Invoke выполняются в одном потоке, дополнительной защиты не требуется.
C#
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
        public void PingIp(object ip)
        {
            var _ip = ip.ToString();
            (string ip, bool correct) result = (_ip, false);
 
            try
            {
 
                Ping ping = new Ping();
                PingReply reply = ping.Send(_ip.ToString());
                if (reply.Options != null/* && reply.RoundtripTime <= 0.5*/)
                {
                    // Task.Delay(1).Wait(); Не нужно. Основной поток и так не блокирован.
                    result.correct = true;
                }
            }
            catch (Exception)
            {
            }
 
            listBox1.Invoke
                (new Action(
                    () => listBox1.Items.Add(result.ip + "    Ping " + (result.correct ? "OK" : "Faild") + "\r\n"))
                );
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            List<Task> tasks = new List<Task>();
            foreach (var s in IPAddressRange.Parse(textBox1.Text))
                tasks.Add(Task.Factory.StartNew(PingIp, s));
 
            // Task.WaitAll(tasks.ToArray()); // Ожидание завершения всех задач
        }
Добавлено через 1 минуту
Цитата Сообщение от uzhsoft Посмотреть сообщение
хак который позволяет разблокировать основной поток
Слип делает блокирующее ожидание.
Не блокирующее - это Task.Delay(123).Wait();.

Добавлено через 1 минуту
Цитата Сообщение от uzhsoft Посмотреть сообщение
нужно заменить на:
Этот список зачем вообще нужен?
Если только для вывода в листбокс, то надо сразу выводить.
1
Злой няш
2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881
07.12.2020, 20:50 13
Цитата Сообщение от Элд Хасп Посмотреть сообщение
C#
1
Task.Delay(1).Wait();
Есть же проще вариант:
C#
1
2
Thread.Yield();
await Task.Yield();
Но непонятно, зачем поток переключать. У Ping есть асинхронная отправка.
0
Модератор
Эксперт .NET
15040 / 10266 / 2708
Регистрация: 21.04.2018
Сообщений: 30,427
Записей в блоге: 2
07.12.2020, 20:59 14
Цитата Сообщение от I2um1 Посмотреть сообщение
Есть же проще вариант:
Это возможно только в асинхронном методе.
Но в данном случае, слип, вообще, излишен.
ТС его ставил для разблокировки UI потока, так как методы выполнялись синхронно в нём.
Если выполнять их в задачах, то в нём потребности нет.

Добавлено через 1 минуту
Я в коде закомментировал эту строку.
0
Злой няш
2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881
07.12.2020, 21:11 15
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Это возможно только в асинхронном методе.
Так там все равно нужно использовать асинхронную отправку и я же два варианта написал, первый - синхронный. В такой реализации и список тасков не нужен, но я не знаю насколько оправдано 254 раза делать Invoke.
0
Модератор
Эксперт .NET
15040 / 10266 / 2708
Регистрация: 21.04.2018
Сообщений: 30,427
Записей в блоге: 2
07.12.2020, 21:25 16
Цитата Сообщение от I2um1 Посмотреть сообщение
В такой реализации и список тасков не нужен, но я не знаю насколько оправдано 254 раза делать Invoke.
Только если каждый пинг буде очень по разному возвращаться.
А вывод результата каждого пинга нужен сразу.

Добавлено через 51 секунду
Я прислал такой вариант, так как не понял причину по какой у ТС долго работает вариант с ожиданием завершения всех задач.
0
958 / 576 / 268
Регистрация: 20.12.2016
Сообщений: 1,506
07.12.2020, 22:01 17
Цитата Сообщение от I2um1 Посмотреть сообщение
Есть же проще вариант
Проще использовать Parallel.For

Добавлено через 3 минуты
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Слип делает блокирующее ожидание.
Да вы правы, я вспомнил что Thread.Sleep(1); используют для разгрузки процессора(чтобы программа позволяла и другим процессам достучаться до CPU).
0
Злой няш
2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881
07.12.2020, 22:01 18
uzhsoft, я ждал веселую реализацию async foreach. Но ладно, Parallel.For действительно проще, наверное.
0
Модератор
Эксперт .NET
15040 / 10266 / 2708
Регистрация: 21.04.2018
Сообщений: 30,427
Записей в блоге: 2
07.12.2020, 22:36 19
Цитата Сообщение от uzhsoft Посмотреть сообщение
Проще использовать Parallel.For
Цитата Сообщение от I2um1 Посмотреть сообщение
я ждал веселую реализацию async
Здесь нет ни какого ожидающего исполнения.
Надо просто запустить задачи и отправить их "в свободное плавание".
Зачем лишние усложнения с await, с Parallel.For?

Если и использовать Parallel то ForEach:
C#
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
        public void PingIp(string ip)
        {
            bool correct = false;
 
            try
            {
 
                Ping ping = new Ping();
                PingReply reply = ping.Send(ip.ToString());
                if (reply.Options != null/* && reply.RoundtripTime <= 0.5*/)
                {
                    correct = true;
                }
            }
            catch (Exception)
            {
            }
 
            listBox1.Invoke
                (new Action(
                    () => listBox1.Items.Add(ip + "    Ping " + (correct ? "OK" : "Faild") + "\r\n"))
                );
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
 
            Parallel.ForEach(IPAddressRange.Parse(textBox1.Text).Select(obj => obj.ToString()), PingIp);
        }
1
Злой няш
2136 / 1505 / 565
Регистрация: 05.04.2010
Сообщений: 2,881
07.12.2020, 23:47 20
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Зачем лишние усложнения с await, с Parallel.For?
Зато как забавно выглядит и не нужен отвратительный Invoke:
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
public static async Task<(string, bool)> PingIp(string ip)
{
    var correct = false;
    try
    {
        var ping = new Ping();
        PingReply reply = await ping.SendPingAsync(ip);
        correct = reply.Options != null;
    }
    catch (Exception)
    {
    }
 
    return (ip, correct);
}
 
public static async IAsyncEnumerable<(string, bool)> PingIPs(IEnumerable<string> ips)
{
    var remaining = ips.Select(PingIp).ToList();
    while (remaining.Count != 0)
    {
        var task = await Task.WhenAny(remaining);
        remaining.Remove(task);
        yield return await task;
    }
}
 
private async void button1_Click(object sender, EventArgs e)
{
    listBox1.Items.Clear();
    IEnumerable<string> ips = IPAddressRange.Parse(textBox1.Text).AsEnumerable().Select(x => x.ToString());
    await foreach ((var ip, var correct) in PingIPs(ips))
    {
        listBox1.Items.Add($"{ip}    Ping {(correct ? "OK" : "Failed")}\r\n");
    }
}
Можно еще ValueTask сюда добавить, абы было. Хотя~, еще более правильнее добавить деление на порции и вернуть Task на клик.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если и использовать Parallel то ForEach
Ну~, этот код замораживает UI, так и не дождался разморозки. Точнее, оно иногда размораживается на долю секунды и снова замораживается.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.12.2020, 23:47
Помогаю со студенческими работами здесь

После двух месяцев работы 1с тормозит все больше и больше
Платформа 8.2 Конфигурация самописная. Толстый Клиент. Файловый вариант базы. 6...

Надо отследить когда консоли CMD. И когда CMD дает результат и запустить по этому событию python программу
Я увлёкся книгой Крейга Ричардсона 'программируем с Minecraft' (Она о том что есть модуль...

Синий экран смерти когда компьютер нагревается или загрузка ЦП больше 80%
У меня стоит Windows 7, постоянно вылетает синий экран. Оперативная память : 2gb Процессор : amd...

Даны натуральные числа N, K, L (K<L). Вывести на экран все делители числа N, которые меньше K или больше L
Даны натуральные числа N, K, L (K&lt;L). Вывести на экран все делители числа N, которые меньше K или...

После создания потока не заходит в функцию этого потока
вот кусок кода: DWORD WINAPI SendToClient(LPVOID ClientSocket); HANDLE hThread; DWORD thID;...

Вывести результат работы программы на экран
задание простое: подсчитать кол-во отрицательных чисел в массиве в принципе, код программы есть:...


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

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

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