Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115

Синхронизировать потоки

23.02.2019, 16:20. Показов 1546. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеется форма и консольное приложение.Имеется 3 потока, нужно синхронизировать их работу между собой, чтобы по-порядку выводили формы 2,3, 4 степени полинома.
Код, где создаются потоки:
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Diagnostics;
 
namespace Лаба2._1
{
    class Program
    {
        static AutoResetEvent waitHandle=new AutoResetEvent(false);
        //static int n;
        static void Main(string[] args)
        {
 
            /*Cоздаем экземпляр класса WorkWithFile, в котором определны функции
             *считывания чисел из файла в двумерный массив и вывода их на экран*/
            WorkWthFile workWthFile = new WorkWthFile();
            /*Cоздаем экземпляр класса Sort, в котором определена функция сортировки двумерного массива*/
            Sort sort = new Sort();
            /*Cоздаем экземпляр класса ConvertTo1, в котором определена функция разделения
             двумерного массива на два одномерных*/
            Convert convert = new Convert();
            /*Cоздаем двумерный массив arrm типа double и инициализуем его функцией считывания чисел из файла*/
            double[,] arrm = workWthFile.FillFile();
            /*создаем переменную size типа int и инициализируем его выходным значением
             *из функции вывода массива на экран */
            int size = workWthFile.OutputCoordinates(arrm);
            /*Вызываем функцию сортировки и передаем в аргументы двумерный массив arrm*/
            sort.SortArray(arrm);
            /*Вызываем функцию вывода массива на экран и передаем в аргументы двумерный массив arrm*/
            sort.DisplayArray(arrm);
            /*Создаем два массива arrx,который отвечает за x,и arry,который отвечает за y.
             *Задаем им размерность size*/
            double[] arrx = new double[size];
            double[] arry = new double[size];
            /*Вызываем функцию разделения двумерного массива на два одномерных.
             Передаем 3 аргумента:arrm(двумерный массив),arrx(точки x),arry(точки y)*/
            convert.ConvertTo1(arrm, arrx, arry);
            /*Цикл по инициализации значений x и y*/
            for (int i = 0; i < size; i++)
            {
                arrx[i] = arrx[i];
                arry[i] = Math.Cos(arrx[i])*Math.Sqrt(arrx[i]); // cos(x)*sqrt(x)
            }
            allStart:
            Console.WriteLine("Введите 1, если хотите посчитать полином 2-4 степени и нарисовать график\n" +
                "Введите 2, если хотите выйти из программмы");
            int choose = int.Parse(Console.ReadLine());
            switch (choose)
            {
                case 1:
                    {
                    //Start:
                        Console.WriteLine("Считаем полиномы 2-4 степени:");
                        /*Console.Write("Введите степень полинома n: ");
                        n = int.Parse(Console.ReadLine());
                        if (n <=1)
            {
                            Console.WriteLine("Полином степени не может быть меньше 1 или равняться 1\n" +
                                "Введите число больше 1");
                            goto Start;*/
                        break; 
            }                    
                case 2:
                    {
                        Environment.Exit(0);
                        break;
                    }
                default:
                    {
                        Console.WriteLine("Введите 1 либо 2");
                        goto allStart;
                    }
            }
            /*Создаем экземпляр класса Task,который позволяет запускать Форму асинхронно в одном из потоков,
             что позволяет обращаться в Форме без последствий*/
            Form1 form = new Form1(arrx, arry, 2,waitHandle);
            Form1 form2 = new Form1(arrx, arry, 3,waitHandle);
            Form1 form3 = new Form1(arrx, arry, 4,waitHandle);
            Thread myThread1 = new Thread(() => form.DrawGraph(arrx, arry, 2));          
            myThread1.Start();
            Thread.Sleep(5);
            form.Show();
            form.Update();
            waitHandle.Set();
            Thread myThread2 = new Thread(() => form2.DrawGraph(arrx, arry, 3));
            myThread2.Start();
            Thread.Sleep(5);
            form2.Show();
            form2.Update(); 
            waitHandle.Set();
            Thread myThread3 = new Thread(() => form3.DrawGraph(arrx, arry, 4));
            myThread3.Start();
            //Thread.Sleep(1000);
            form3.Show();
            form3.Update();
            waitHandle.Set();
            //waitHandle.Reset();
            
            
            
            //});
метод(В форме), который передаем в поток:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    public partial class Form1 : Form
    {
        private readonly AutoResetEvent mre1 = new AutoResetEvent(false);
        private readonly AutoResetEvent mre2 = new AutoResetEvent(false);
        static object locker = new object();
        private AutoResetEvent waitHandle;
        private double[] arrx;
        private double[] arry;
        private int i;
        /*Конструктор класса Form1*/
        public Form1(double[] arrx, double[] arry, int i,AutoResetEvent waitHandle)
        { 
                this.arrx = arrx;
                this.arry = arry;
                this.i = i;
            this.waitHandle = waitHandle;
        InitializeComponent();
        }
        public Form1()
        {
 
        }
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
public void DrawGraph(double[] x, double[] y,int n)
        {
          // waitHandle.WaitOne();
            Thread.Sleep(500);
            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();
            mre1.Set();
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.02.2019, 16:20
Ответы с готовыми решениями:

Как правильно синхронизировать потоки?
По нажатию кнопки создается N потоков (в данном случае 5): Thread threads = new Thread; for (int i = 0; i &lt;...

Замедлится ли работа приведенного кода, если синхронизировать потоки
Допустим , мы написали программу, который многопоточно брутит пароли (подбирает). Пример функции потока: void...

Байтовые потоки и потоки символов
Объясните, пожалуйста подробно что имелось ввиду На самом низком уровне все операции ввода/вывода в С# оперируют байтами. Подобный...

5
17 / 14 / 7
Регистрация: 04.02.2017
Сообщений: 486
23.02.2019, 16:37
вы хотите по порядку чтоб сначала первый поток вывел все результаты до конца, затем воторой и в конце третий?
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 16:39  [ТС]
FerrariF70, Да
0
17 / 14 / 7
Регистрация: 04.02.2017
Сообщений: 486
23.02.2019, 16:57
У вас есть разделяемый ресурс этот ресурс называется консольное окно, куда вы будете выводить свои результаты вам просто надо на ваши циклы поставить блокираторы типа lock или monitor

C#
1
2
3
4
5
6
7
8
object block = new object();
 
lock(block)
{
  for(int i = 0; i < 10; i++){
    //Вывод на экран
   }
{
или
C#
1
2
3
4
5
Monitor.Enter(block);
for(int i = 0; i < 10; i++){
    //Вывод на экран
   }
Monitor.Exit(block);
вам даже не надо Thread.Sleep() использовать это блокирует поток что остальные потоки не заходили в эту область они дожидаются пока определённый поток не закончит вывод до конца.
0
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 115
23.02.2019, 17:05  [ТС]
FerrariF70, А нельзя ли как-то реализовать через события manualResetEvent?

Добавлено через 4 минуты
FerrariF70, Вроде как я смог сделать
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
 /*Создаем экземпляр класса Task,который позволяет запускать Форму асинхронно в одном из потоков,
             что позволяет обращаться в Форме без последствий*/
            Form1 form = new Form1(arrx, arry, 2,waitHandle);
            Form1 form2 = new Form1(arrx, arry, 3,waitHandle);
            Form1 form3 = new Form1(arrx, arry, 4,waitHandle);
            Thread myThread1 = new Thread(() => form.DrawGraph(arrx, arry, 2,waitHandle));          
            myThread1.Start();
            waitHandle.WaitOne();
            //Thread.Sleep(1000);
            form.Show();
            form.Update();
            waitHandle2.Set();
            Thread myThread2 = new Thread(() => form2.DrawGraph(arrx, arry, 3,waitHandle));          
            myThread2.Start();
            waitHandle.WaitOne();
            //Thread.Sleep(1000);
            form2.Show();
            form2.Update();
            waitHandle2.Set();
            Thread myThread3 = new Thread(() => form3.DrawGraph(arrx, arry, 4, waitHandle));      
            myThread3.Start();
            waitHandle.WaitOne();
            //Thread.Sleep(1000);
            form3.Show();
            form3.Update();
            waitHandle2.Set();
            //waitHandle.Reset();
правильно ли?
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
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();
        private AutoResetEvent waitHandle;
        private double[] arrx;
        private double[] arry;
        private int i;
        /*Конструктор класса Form1*/
        public Form1(double[] arrx, double[] arry, int i,AutoResetEvent waitHandle)
        { 
                this.arrx = arrx;
                this.arry = arry;
                this.i = i;
            this.waitHandle = waitHandle;
        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,AutoResetEvent waitHandler)
        {
            Thread.Sleep(500);
            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.Set();
0
17 / 14 / 7
Регистрация: 04.02.2017
Сообщений: 486
23.02.2019, 17:31
Лучший ответ Сообщение было отмечено artur31154 как решение

Решение

ManualResetEvent никогда сним не пользовался да и не думаю что оно вам поможет так как оно уведомляет один или более ожидающих потоков что произашло событие а если произашло событие то все потоки которые увас есть рванут к этому событию и снова каждый поток не будет дожидатся пока первый поток закончит свою работу вывода.

Добавлено через 5 минут
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
 public void DrawGraph(double[] x, double[] y,int n,AutoResetEvent waitHandler)
        {
           lock(locker){
            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.Set();
           }
попробуйте так

Добавлено через 4 минуты
Monitor нету в формах поэтому воспользуйтесь lcok как я написал
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.02.2019, 17:31
Помогаю со студенческими работами здесь

Синхронизировать через стэк
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using...

Синхронизировать сайт с сервером
Сайт сможет делать запросы на сервер написанный на с#?

ManualResetEvent: синхронизировать три потока
static void Main(string args) { ManualResetEvent mre = new ManualResetEvent(true); Text txt = new...

Синхронизировать поток ключевым словом lock
Есть задание, чтобы программа напоминала что-то вроде турникета, где пассажиры бы становились в очередь, бросали монетку(жетон) проходили...

Как синхронизировать один таймер со вторым?
Работают 2 таймера синхронно. Второй должен отключаться, но при включении они уже будут работать в разнобой. Как второй таймер подстроить...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru