Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.50/22: Рейтинг темы: голосов - 22, средняя оценка - 4.50
 Аватар для Hermein
99 / 43 / 16
Регистрация: 25.10.2011
Сообщений: 246
.NET 2.x

Многопоточность

19.11.2011, 12:12. Показов 4802. Ответов 26
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет, встала резко задача использования многопоточности без повторения переменных массива
Итак имеется массив mas состоящий из 100 элементов от 0 до 99, мне необходимо вывести все эти элементы в 1-10 потоков.

Как это сделать вообще не понимаю.
C#
1
2
3
4
5
6
7
            Thread[] thread = new Thread[10];            
            for (int i = 0; i < 10; i++)
            {
                thread[i]= new Thread(new ThreadStart(potok));
                thread[i].IsBackground = true;
                thread[i].Start();
            }
Запускаем 10 потоков, а дальше что?
ps: вариант с lock отпадает сразу, я с ним могу сделать, но он блокирует другие потоки и получается процесс выполняться будет в 1 поток
т.е
C#
1
2
3
4
5
6
7
8
void potok()
{
lock(this)
{
//здесь исполняемы код
}
 
}
Не подходит вариант!
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.11.2011, 12:12
Ответы с готовыми решениями:

Многопоточность
Доброго времени суток! Пишу довольно редко, самостоятельно не получилось разобраться:( Сразу перейду к задаче. Допустим есть цикл: ...

Многопоточность
Имеется класс class MainMeneger: Form, в нем объявляются интерфейсы public IMainForm view; public IMessegeService messege; public...

Многопоточность
Доброго времени суток. Делаю задачу на запуск самолетов. Самолет - объект класса, который обладает параметрами: скорость, направление,...

26
185 / 185 / 53
Регистрация: 10.04.2009
Сообщений: 491
19.11.2011, 12:59
мютексы, семафоры, замки - все это используется для синхронизации, а это очень обширная тема
если вывести массив в потоках, можно обойтись и проще вариантами
C#
1
2
3
Parallel.For(0,100,i=>{
Console.WriteLine(someArray[i]);
});
0
 Аватар для Hermein
99 / 43 / 16
Регистрация: 25.10.2011
Сообщений: 246
19.11.2011, 13:55  [ТС]
Parallel нет в .Net Framework 2.0
Можно с List-ами работать, но бывает что хавает 2 раза 1 и то же значение
Просто ctrl+c ctrl+v не вариант тоже использовать....
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
19.11.2011, 14:39
Цитата Сообщение от Hermein Посмотреть сообщение
.Net Framework 2.0
Так пересядьте на .NET 4.0, чего в каменном веке телепаться?

Ну или если вам хорошо с динозаврами, то вручную разбивайте список на сегменты и давайте каждому потоку на обработку отдельный сегмент.
В общем-то, в Parallel примерно то же самое и происходит.
0
 Аватар для Hermein
99 / 43 / 16
Регистрация: 25.10.2011
Сообщений: 246
19.11.2011, 15:51  [ТС]
kolorotur, я смотрю вы только умничаете, а конкретного ничего, пробовал я передавать печеньки в поток и ничего хорошего не получилось! А про переходи на 4 это мне решать, мне он нафиг не нужен, мне нужен .Net Framework 2.0 и не эра это ждинозавров, просто я привык на нем работать, а переходить на фреймы более высшие с кучей лагов и ненужных функций не хочется!
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
19.11.2011, 15:54
Hermein, Лол. Язык развивается. Новые плюшки. Новые исправления. Новые баги конечно тоже, но плюшек-то больше. А кто вам сказал, что вам будут здесь расписывать по полочкам? Есть Parallel, не хотите обновляться? Делайте сами, в посте №4 подсказали как. А готового кода здесь не будет.
1
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
19.11.2011, 17:36
Вот держи. Во втором фрэймворке работает. Тут я cделал в консоли, без отдельных классов, просто неохота было заморачиваться (хоть и делал от нечего делать, просто почему-то мне стало интересно). А так можешь переделать и написать свой TPL (грубо говоря ).

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
using System;
using System.Collections.Generic;
using System.Threading;
 
namespace Cons_Threads
{
    class Program
    {
        static void Main(string[] args)
        {
            const int quantityParts = 10;
 
            string[] elements = new string[100];
            for (int i = 0; i < elements.Length; i++)
                elements[i] = "[" + i + "]";
 
            List<string>[] dividedElements = DivideIntoParts<string>(elements, quantityParts);
 
            Thread[] thread = new Thread[quantityParts];
            for (int i = 0; i < quantityParts; i++)
            {
                thread[i] = new Thread(new ParameterizedThreadStart(DoWork));
                thread[i].IsBackground = true;
                thread[i].Start(dividedElements[i]);
            }
 
            Console.ReadKey();
        }
 
        static void DoWork(object data)
        {
            List<string> dataList = data as List<string>;
            if (dataList == null)
                throw new NullReferenceException();
 
            foreach (string item in dataList)
                Console.WriteLine(item);
        }
 
        /// <summary>
        /// Разделить коллекцию на части.
        /// </summary>
        /// <typeparam name="T">Тип элементов коллекции</typeparam>
        /// <param name="collection">Коллекция, которую нужно разделить</param>
        /// <param name="quantityParts">Количество частей, на которое будет разделена коллекция</param>
        /// <returns></returns>
        static List<T>[] DivideIntoParts<T>(IList<T> collection, int quantityParts)
        {
            if (collection == null)
                throw new NullReferenceException();
            if (collection.Count < quantityParts)
                throw new Exception("Коллекция содержит меньшее кол-во элементов, чем кол-во частей, на которые нужно её разделить");
 
            List<T>[] lists = new List<T>[quantityParts];
            for (int i = 0; i < lists.Length; i++)
                lists[i] = new List<T>();
 
            int counter = 0;
 
            for (int i = 0; i < collection.Count; i++)
            {
                lists[counter].Add(collection[i]);
                if (++counter == quantityParts)
                    counter = 0;
            }
 
            return lists;
        }
    }
}
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
19.11.2011, 18:08
Цитата Сообщение от Hermein Посмотреть сообщение
я смотрю вы только умничаете, а конкретного ничего
Уважаемый, я вам не хамил. Будьте добры в таком ключе с папой разговаривать (если он у вас есть и вы его знаете).
По поводу конкретики можете посмотреть другие мои сообщения.

Цитата Сообщение от Hermein Посмотреть сообщение
пробовал я передавать печеньки в поток и ничего хорошего не получилось!
Ну так надо было показать код, в котором ничего хорошего не получилось. Наверняка всё поправимо.

Цитата Сообщение от Hermein Посмотреть сообщение
фреймы более высшие с кучей лагов
Не скажите. Как раз-таки четрвертый фреймворк затачивался на параллельные вычисления, потому именно в многопотоковых приложениях он работает намного шустрее, чем предыдущие. В основном засчет более быстрой реализации механизмов для синхронизации потоков.
Ну это я так, сумничал

В целом же, вот вам простенький пример как вывести массив в 100 элементов из десяти потоков, где каждый поток выводит свою часть:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void Main(string[] args)
{
    int[] arr = new int[100];
    for (int i = 0; i < 10; i++) {
        int offset = i;
        new Thread(delegate(object o) {
            Print(arr, offset * 10, 10);
        }).Start();
    }
}
 
static void Print(int[] arr, int offset, int count)
{
    for (int i = offset; i < offset + count; i++)
        Console.WriteLine(arr[i]);
}
Если не ошибаюсь, анонимные методы появились как раз во втором фрэймворке, потому должно работать.
Если вам надо чтобы выводилось по порядку, то можно добавить синхронизацию, но в этом случае теряется смысл разбивания на потоки, т.к. каждый последующий поток должен будет ждать окончания работы предыдущего.
1
19.11.2011, 19:07

Не по теме:

Цитата Сообщение от kolorotur Посмотреть сообщение
В целом же, вот вам простенький пример как вывести массив в 100 элементов из десяти потоков, где каждый поток выводит свою часть:
Нормально! Я как всегда нагородил :).

0
 Аватар для Hermein
99 / 43 / 16
Регистрация: 25.10.2011
Сообщений: 246
20.11.2011, 11:45  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void Main(string[] args)
{
    int[] arr = new int[100];
    for (int i = 0; i < 10; i++) {
        int offset = i;
        new Thread(delegate(object o) {
            Print(arr, offset * 10, 10);
        }).Start();
    }
}
 
static void Print(int[] arr, int offset, int count)
{
    for (int i = offset; i < offset + count; i++)
        Console.WriteLine(arr[i]);
}
Спасибо большое все работает как нужно, по порядку не надо, ибо там с синхронизацией получается по аналогии с локом.
1 вопрос еще - new Thread(delegate(object o) {
Print(arr, offset * 10, 10);
}).Start();
Что означает данная строка, точнее delegate(object o) {}-что это за делегат и для чего он нужен?
Нельзя использовать например так, просто сложно как-то с потоками:
C#
1
2
3
4
5
6
7
8
9
10
Thread[] thread=new Thread[10];
for(int i=0;i<10;i++)
{
thread[i]=new Thread(potok);
thread[i].Start(arr, offset * 10, 10);
}
void potok(int[] arr, int offset, int count)   
{
//
}
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
20.11.2011, 12:31
Цитата Сообщение от Hermein Посмотреть сообщение
Нельзя использовать например так, просто сложно как-то с потоками
Ну так я же выложил вариант без delegate (в смысле ключевого слова). Если разделение массива не подходит, то можно в
целевой метод
в данном случае DoWork(object data)
передавать например
C#
1
Dictionary<string, object> dictionary;
потом в целевом методе разбирать по ключу и получать данные (offset, сам массив и т.д.). Можно что угодно передавать и в методе разбирать на части, или сделать специальный объект, короче тут вариантов очень много.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
20.11.2011, 12:46
Цитата Сообщение от Hermein Посмотреть сообщение
Что означает данная строка, точнее delegate(object o) {}-что это за делегат и для чего он нужен?
Это анонимный метод - позволяет объявить новый метод прямо в теле другого метода, порой довольно неплохо сокращает код.
Конструктор класса Thread принимает либо делегат ThreadStart, который по сути дела является указателем на метод вида void Foo(). То есть не возвращает значения и не принимает аргументов. Либо делегат вида ParametrizedThreadStart, который имеет вид void Foo(object o), то есть принимает один аргумент типа object. Так как нам надо передать в поток не одну, а три переменных, надо либо оборачивать их в структуру или класс, либо создавать тот самый анонимный метод и в нем просто запускать нужный нам код. Аргумент анонимного метода "object o" в данном случае там ничего не делает, он нужен только для того, чтобы подпись метода совпадала с требованием делегата ThreadStart.
Если не пользоваться анонимным методом, то придется обернуть значения для передачи:
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
struct ThreadArg
{
    public int[] arr;
    public int offset;
    public int count;
 
    public ThreadArg(int[] arr, int offset, int count)
    {
        this.arr = arr;
        this.offset = offset;
        this.count = count;
    }
}
 
static void Main(string[] args)
{
    int[] arr = new int[100];
    for (int i = 0; i < 10; i++) {
        Thread thread = new Thread(ThreadCallback);
        thread.IsBackground = true;
        thread.Start(new ThreadArg(arr, i * 10, 10)); // Передача в поток данных, обернутых в структуру
    }
}
 
static void ThreadCallback(object o)
{
    ThreadArg arg = (ThreadArg)o; // Каст объекта к нужному типу
    Print(arg.arr, arg.offset, arg.count);  // Запуск метода Print с полученными в структуре аргументами
}
 
static void Print(int[] arr, int offset, int count)
{
    for (int i = offset; i < offset + count; i++)
        Console.WriteLine(arr[i]);
}
Как видите, без использования анонимного метода пришлось добавить дополнительную структуру для передачи данных в поток и дополнительный метод, который кастит объект в нужный тип и запускает метод для распечатки.
В принципе, дополнительный метод ThreadCallback можно убрать и просто передавать один аргумент типа object в метод Print, который его откастит сам, но с точки зрения архитектуры не стоит менять подпись метода для подгона ее под тип вызова.

Цитата Сообщение от Hermein Посмотреть сообщение
Нельзя использовать например так
Нет, нельзя, потому что класс Thread принимает на вход только методы со следующей подписью:
void F()
void F(object o)
Как видим, там нет метода, принимающего три значения. Потому либо не передаем вообще ничего, либо передаем всего один объект.
2
 Аватар для Hermein
99 / 43 / 16
Регистрация: 25.10.2011
Сообщений: 246
20.11.2011, 13:06  [ТС]
Заметил закономерность, что если число потоков более 5...то это провал....некоторые значения могут вылетать....очень странно!!!
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
20.11.2011, 13:08
Цитата Сообщение от Hermein Посмотреть сообщение
Заметил закономерность, что если число потоков более 5...то это провал....некоторые значения могут вылетать....очень странно!!!
Есть конкретный пример, то есть чтобы можно было увидеть вылет?
0
 Аватар для Hermein
99 / 43 / 16
Регистрация: 25.10.2011
Сообщений: 246
20.11.2011, 13:13  [ТС]
Цитата Сообщение от Casper-SC Посмотреть сообщение
Есть конкретный пример, то есть чтобы можно было увидеть вылет?
пример дан выше при 10 потоках и 1000 значений передаваемых получается провал!
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
 private void button1_Click(object sender, EventArgs e)
        {
            list.Clear();
            for (int i = 0; i < 1000; i++)
            {
                list.Add(i);
            }
            for (int i = 0; i < 10; i++)
            {
                int offset = i;
                new Thread(delegate(object o)
                {
                    Print(list.ToArray(), offset * 100, 100);
                }).Start();
            }
        }
        string lol = "";
        void Print(int[] arr, int offset, int count)
        {
            for (int i = offset; i < offset + count; i++)
            {            
              lol += arr[i] + "\r\n";                
            }
            richTextBox1.Invoke(new EventHandler(delegate
            {
                if (richTextBox1.Text.Length <= 1)
                {
                    richTextBox1.AppendText(lol);
                    lol="";
                }
            }));
        }
Аналогично и своим путем:
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
List<int> list = new List<int>();
  private void button3_Click(object sender, EventArgs e)
        {
            list.Clear();
            for (int i = 0; i < 1000; i++)
            {
                list.Add(i);
            }
            Thread[] thread = new Thread[10];
            for (int i = 0; i < 10; i++)
            {
                thread[i] = new Thread(new ThreadStart(potok));
                thread[i].Start();
               // Thread.Sleep(20);
            }            
 
        }
        void potok()
        {
            if (list != null && list.Count > 0)
            {
                int res = list[0];
                list.RemoveAt(0);
                lol += res + "\r\n";
                Thread th = new Thread(new ThreadStart(potok));
                th.Start();
            }
            else 
            {
                richTextBox1.Invoke(new EventHandler(delegate
                {
                    if (richTextBox1.Text.Length <= 1)
                    {
                        richTextBox1.AppendText(lol);
                        lol = "";
                    }
                }));
            }
}

ps: при числе потоков 5 и менее оба способа работают безотказно
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
20.11.2011, 13:18
Помоему надо лочить RichTextBox при добавлении в него.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
20.11.2011, 13:22
Что вы подразумеваете под словом "провал"? Вылетает исключение? Некоторые числа не отображаются?
0
 Аватар для Hermein
99 / 43 / 16
Регистрация: 25.10.2011
Сообщений: 246
20.11.2011, 13:28  [ТС]
Цитата Сообщение от Casper-SC Посмотреть сообщение
Помоему надо лочить RichTextBox при добавлении в него.
Его лочить надо, если мы постоянно в него добавляем, а так все добавляется в переменную, которая потом разово записывается в рич.


Цитата Сообщение от kolorotur Посмотреть сообщение
Некоторые числа не отображаются
При числе потоков 5 и меньше все ок, больше 5, числа некоторые не отображаются
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
20.11.2011, 13:31
Цитата Сообщение от Hermein Посмотреть сообщение
Его лочить надо, если мы постоянно в него добавляем, а так все добавляется в переменную, которая потом разово записывается в рич.
Да я уже увидел. У себя потестил, что-то и в правду пропускает значения. Я просто это написал не посмотрев внимательно код.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
20.11.2011, 13:31
Цитата Сообщение от Hermein Посмотреть сообщение
числа некоторые не отображаются
Явный признак отсутствия синхронизации.
У вас текстовая переменная тоже глобальная для всех потоков, вот они и затирают изменения, внесенные другими потоками. Облочьте ее.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.11.2011, 13:31
Помогаю со студенческими работами здесь

Многопоточность
вообщем вот что имею public int index = -1; public int count = 10; private static readonly object SyncIndex = new...

Многопоточность
Здравствуйте. Столкнулся с проблемой, при работе с многопоточностью. Потоки создал так: private void...

Многопоточность
Всем привет. Как реализовать многопоточность с выбором количества потоков? Буду очень благодарен.

Многопоточность
Доброго времени суток всем. Народ задача стоит многопоточное умножение матриц. Ну если я правильно всё догнал, то получается примерно...

Многопоточность в C#
Уважаемые, программисты! Помогите, пожалуйста, реализовать пример с потоками. Мне нужно для примера, чтобы в первом потоке на форме...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG-файла с альфа-каналом с помощью библиотеки SDL3_image на Android
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru