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

Проблема с потоками

23.02.2019, 04:07. Показов 3478. Ответов 17
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Проблема заключается в том, что создается только один поток, а мне нужно 3 потока.
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
 /*Создаем экземпляр класса Task,который позволяет запускать Форму асинхронно в одном из потоков,
             что позволяет обращаться в Форме без последствий*/
             for(int i = 2; i < 5; i++)
            {
                //Task myTask = Task.Run(() =>
            //{
                /*Создаем экземпляр класса Form1(Нашей формы,в которой происходит построение графика)*/
                Form1 form = new Form1(arrx, arry, i);
                /*Вызываем функция DrawGraph,которая как раз-таки отвечает за инициализацию
                 * и построение графика*/
                //new Thread(() => form.DrawGraph(arrx, arry, i)).Start();
                Thread myThread= new Thread(() => form.DrawGraph(arrx, arry, i));
                myThread.Start();
                //myThread[i].Name = "Поток полинома " + i.ToString() + " степени";
                Console.WriteLine("Поток №{0}",Thread.CurrentThread.GetHashCode()); 
                //Console.WriteLine(myThread[i].Name); 
                //Thread myThread= new Thread(new ThreadStart (form.DrawGraph));
                //myThread.Name = "Поток полинома" + i.ToString()+ "степени ";
                //myThread.Start();
                //form.DrawGraph(arrx, arry,n);
                /*Показываем форму,в которой уже нарисовался график функции*/
                form.ShowDialog();
               //hread.Sleep(500);
            //});
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.02.2019, 04:07
Ответы с готовыми решениями:

Проблема с потоками.
Пробую написать IRC бота на шарпе. В отдельном процессе запускается пинг сервера метод...

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

проблема с потоками
Ребят при написании программы появилась проблема, опишу вкратце. пишу интерфейс WTL шаблонами. В...

Проблема с потоками
Здравствуйте. Подскажите пожалуйста. Проблема такая. Программа из этого примера...

17
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 08:12 2
Цитата Сообщение от artur31154 Посмотреть сообщение
создается только один поток
на основании чего сделан такой вывод?
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 10:49  [ТС] 3
asn31337, на основании того, что вывожу номер текущего потока, а он всегда равен одному
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 11:28 4
Цитата Сообщение от artur31154 Посмотреть сообщение
вывожу номер текущего потока, а он всегда равен одному
Неверная у Вас логика))) Дело в том, что у Вас в цикле открывается форма в режиме диалога. Пока форма не будет закрыта, новая итерация не начнется. Тем временем поток завершает свою работу и на новой итерации стартует с тем же номером. Попробуйте открывать форму не модально. По идее, должно открыться 3 формы, каждая из которых будет отработана своим потоком.
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 11:32  [ТС] 5
asn31337, То есть, вы предлагаете использовать Task.run?Просто, если использовать его, то работает все в отдельных потоках, но мне казалось, что есть другие способы
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 11:34 6
Цитата Сообщение от artur31154 Посмотреть сообщение
То есть, вы предлагаете использовать Task.run?
Нет. Я предлагаю вместо form.ShowDialog(); использовать form.Show();
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 11:37  [ТС] 7
asn31337, Если так, то все также один поток все обрабатывает
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 11:43 8
Цитата Сообщение от artur31154 Посмотреть сообщение
также один поток все обрабатывает
Значит, просто работа потока занимает очень мало времени и к моменту второй итерации поток уже отрабатывает (попробуйте искусственно затормозить работу метода, который выполняется в потоке, например, Thread.Sleep).
А в чем принципиальность именно 3-х потоков?
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 11:46  [ТС] 9
asn31337, Мне нужно, чтобы каждый из потоков обрабатывал свой полином n-ой степени, то есть 2-ой поток обрабатывает вторую степень и так далее.Мне нужно как-то синхронизировать их работу с помощью ManualResetEvent или AutoResetEvent

Добавлено через 57 секунд
asn31337, И еще, я заметил, что если использовать просто Show, то форма не может загрузится, просто белое окно.Так что, это не выход :C
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 11:57 10
Лучший ответ Сообщение было отмечено artur31154 как решение

Решение

artur31154, чет я сразу то не обратил внимание... Вы номер выводите всегда для основного потока))) Чтобы вывести номер запущенного перенесите строку
C#
1
Console.WriteLine("Поток №{0}",Thread.CurrentThread.GetHashCode());
в тело потока.

Цитата Сообщение от artur31154 Посмотреть сообщение
если использовать просто Show, то форма не может загрузится, просто белое окно
только что проверил, все норм работает. если не грузится форма, значит где то в коде косяк.
1
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 12:02  [ТС] 11
asn31337, Так, больше Вам спасибо!.И еще, можно как-то синхронизировать эти потоки с помощью autoResetEvent или ManualResetEvent?
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 12:18 12
Лучший ответ Сообщение было отмечено artur31154 как решение

Решение

Цитата Сообщение от artur31154 Посмотреть сообщение
можно как-то синхронизировать эти потоки с помощью autoResetEvent или ManualResetEvent?
А в чем должна заключаться синхронизация? Эвенты просто имеют 2 состояния - сигнальное и несигнальное. Т.е. можно, к примеру, послать сигнал и поток будет приостановлен до получения сигнала. Под синхронизацией обычно подразумевается использование несколькими потоками одной и той же переменной. Если все потоки только читают ее, то синхронизация вообще не нужна. Если же возможно изменение значения переменной во время работы потока, то используют lock, mutex или семафоры.
1
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 12:51  [ТС] 13
asn31337, asn31337, чтобы каждый поток выполнялся по-очереди строго

Добавлено через 26 минут
asn31337, В общем, с синхронизацией потоков с помощью события я вроде бы разобрался.Теперь проблема с Show, она отображается белое окно, которое даже закрыть нельзя с помощью крестика.Вот код:
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using ZedGraph;
 
namespace Лаба2._1
{
    /*Форма Form1 для построения графиков,которая наследуется от класса Form,в котором описаны начальные инструкции*/
    public partial class Form1 : Form
    {
        static object locker = new object();
        static EventWaitHandle waitHandle = new AutoResetEvent(false);
        private double[] arrx;
        private double[] arry;
        private int i;
        /*Конструктор класса Form1*/
        public Form1(double[] arrx, double[] arry, int i)
        { 
                this.arrx = arrx;
                this.arry = arry;
            this.i = i;
        InitializeComponent();
        }
        public Form1()
        {
 
        }
        /*функция вычисления интерполяционного полинома лагранжа,которая принимает в аргументы значение x
         *и два одномерных массива x,y типа double*/
        public double Lagrange(double x0, double[] x, double[] y)
        {
            /*Объявление переменной polinom типа double и инициализация нулем*/
            double polinom = 0;
            /*Цикл вычисления интерполяционного полинома Лагранжа*/
            for (int j = 0; j < x.Length; j++)
            {
                /*Объявление переменной p типа double и инициализация единицей*/
                double p = 1;
                /*Цикл вычисление базисных полиномов*/
                for (int i = 0; i <x.Length; i++)
                    if (j != i)
                    {
                        /*Вычисление базисных полиномов по формуле Лагранжа*/
                        p *=  (x0 - x[i]) / (x[j] - x[i]);
                    }
                /*Вычисление интерполяционного полинома Лагранжа*/
                polinom += y[j] * p;
            }
            /*Возвращение значения polinom*/
            return polinom;
        }
        /*Функция,которая добавляет точки на график и рисует график функции,принимающая два массива x,y типа double*/
        public void DrawGraph(double[] x, double[] y,int n,EventWaitHandle waitHandle)
        {
            
            Console.WriteLine("Поток №{0}", Thread.CurrentThread.GetHashCode());
            /* Получим панель для рисования*/
            GraphPane pane = zedGraphControl1.GraphPane;
            pane.Title.Text = "Интерполяционный полином Лагранжа";            
            /*Предварительно очищаем панель*/
            pane.CurveList.Clear();
            /*Создадим список точек*/
            PointPairList list_1 = new PointPairList();
            PointPairList list_2 = new PointPairList();
            /*Заполняем список точек*/
            for (int i = 0; i < x.Length; i++)
            {
                list_1.Add(x[i], y[i]);
            }
 
            /*Интерполируем несколько точек между узлами*/
            for (int i = 0; i < x.Length-1 ; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    /*Объявляем переменную local типа double и присваиваем выражение,по которому вычисляется будущий x*/
                    double local = x[i] + j * (x[i + 1] - x[i])/n;
                    /*Заполнение списка точек,кроме последней точки,
                     *вызовом функции вычисления интерполяционного полинома Лагранжа*/
                    list_2.Add(local, Lagrange(local, x, y));
                }
            }
            /*Добавление последней точки в список*/
            list_2.Add(x[x.Length - 1], y[y.Length - 1]);
            /*Объявляем два экземпляра класса LineItem.Рисуем линии по точкам*/
            Console.WriteLine("Рисую график, пожалуйста, подождите");
            LineItem myCurve1 = pane.AddCurve("Исходная функция", list_1, Color.Purple, SymbolType.Diamond);
            LineItem myCurve2 = pane.AddCurve("Интерполяционный полином", list_2, Color.Red, SymbolType.None);
            Console.WriteLine("График готов!");
            /* По оси Y установим автоматический подбор масштаба*/
            pane.YAxis.Scale.MinAuto = true;
            pane.YAxis.Scale.MaxAuto = true;
            /*Установим значение параметра IsBoundedRanges как true.
              Это означает, что при автоматическом подборе масштаба 
              нужно учитывать только видимый интервал графика*/
            pane.IsBoundedRanges = true;
            /*Обновляем данные об осях*/
            pane.AxisChange();
            /*Обновляем график*/
            zedGraphControl1.Invalidate();
          waitHandle.WaitOne();
            
            
        }
        /*private void zedGraphControl1_Load(object sender, EventArgs e)
        {
 
        }*/
 
        /*private void zedGraphControl1_Load(object sender, EventArgs e)
        {
 
        }*/
    }
 
}
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 12:56 14
Цитата Сообщение от artur31154 Посмотреть сообщение
чтобы каждый поток выполнялся по-очереди строго
А зачем тогда вообще нужно несколько потоков, если они все равно должны работать по-очереди?
Ну, если очень хочется... Тогда примерно так должно быть:
1. Надо создать 2 глобальных переменных типа ManualResetEvent (обе в несигнальном состоянии).
2. Создаем и запускаем все 3 потока, но во 2-м и 3-м первой строкой ждем сигнального состояния ManualResetEvent.
3. по завершении 1-го потока устанавливаем 1-ю переменную в сигнальное состояние - начинает выполняться второй поток
4. по завершении 2-го потока устанавливаем 2-ю переменную в сигнальное состояние - выполняется 3-й поток.

Это очень примерно, так сказать набросок...
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 13:01  [ТС] 15
asn31337, я это смог реализовать, теперь проблема в форме, так как мне нужно, чтобы сразу отобразились все формы n-ой степени поочереди, поэтому для этого целесобразно использовать Show(), но он почему-то не работает у меня, понять не могу.А ShowDialog не подходит, так как он блокирует все остальные формы и они не выводятся, пока не закроешь эту форму
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 13:17 16
Цитата Сообщение от artur31154 Посмотреть сообщение
C#
1
static EventWaitHandle waitHandle = new AutoResetEvent(false);
переменная находится в несигнальном состоянии и ее значение нигде не меняется. получается код доходит до строки
Цитата Сообщение от artur31154 Посмотреть сообщение
C#
1
waitHandle.WaitOne();
и "зависает" в ожидании сигнала...

Добавлено через 1 минуту
Возможно, дело не только в этом, но это тоже косяк)))

Добавлено через 9 минут
И, кстати, не очень понял... Form1 - это единственная форма или еще есть? Приложение как запускается?
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 14:14  [ТС] 17
asn31337, да, это единственная форма,а запускается она через консольное приложение в методе main

Добавлено через 52 минуты
asn31337, А зачем тогда вообще нужно несколько потоков, если они все равно должны работать по-очереди?
Ну, если очень хочется... Тогда примерно так должно быть:
1. Надо создать 2 глобальных переменных типа ManualResetEvent (обе в несигнальном состоянии).
2. Создаем и запускаем все 3 потока, но во 2-м и 3-м первой строкой ждем сигнального состояния ManualResetEvent.
3. по завершении 1-го потока устанавливаем 1-ю переменную в сигнальное состояние - начинает выполняться второй поток
4. по завершении 2-го потока устанавливаем 2-ю переменную в сигнальное состояние - выполняется 3-й поток.

Это очень примерно, так сказать набросок...

А можете подробнее описать?
0
Фрилансер
805 / 312 / 148
Регистрация: 13.02.2019
Сообщений: 1,071
23.02.2019, 20:06 18
Лучший ответ Сообщение было отмечено artur31154 как решение

Решение

Цитата Сообщение от artur31154 Посмотреть сообщение
А можете подробнее описать?
Навскидку:
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
        static ManualResetEvent start2 = new ManualResetEvent(false);
        static ManualResetEvent start3 = new ManualResetEvent(false);
        
        static void Main(string[] args)
        {
            for(int i = 0; i < 3; i++)
            {
                Thread t = new Thread((object obj) =>
                {
                    int a = (int)obj;
 
                    if (a == 1)
                    {
                        start2.WaitOne();
                    }
                    else if (a == 2)
                    {
                        start3.WaitOne();
                    }
 
                    Console.WriteLine($"Thread {a} started");
                    Thread.Sleep(1000);
                    Console.WriteLine($"Thread {a} stopped");
 
                    if (a == 0)
                        start2.Set();
                    else if (a == 1)
                        start3.Set();
                });
                t.Start(i);
            }
            Console.ReadKey();
        }
0
23.02.2019, 20:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.02.2019, 20:06
Помогаю со студенческими работами здесь

Проблема с потоками
По нажатию кнопки происходит сложный метод, но перед тем как метод выполнять я просто хочу чтобы...

Проблема с потоками (файлы)
В коде программы необходимо несколько раз открывать один и тот же файл. Проблема в том, когда...

Проблема при работе с потоками
Помогите решить тупую проблему! Есть массив строк: String MassStr = new String{'one', 'two',...

Проблема с широкими потоками(wofstream)
Вот такое дело. Код: w_char* xmlRezult;//здесь хранится имя файла wstringstream*...


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

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

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