2 / 2 / 3
Регистрация: 19.08.2013
Сообщений: 100
1

Синхронизация двух потоков с общей переменной

21.02.2017, 20:45. Показов 3401. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
добрый вечер, стоит следующая задача:
Напишите программу, в которой первый поток построчно считывает содержимое некоторого текстового файла, последовательно передавая полученные строки второму потоку. Второй поток преобразовывает каждую поступившую строку (приводит все символы к верхнему регистру) и выводит ее на экран. Для обмена данными между потоками использовать глобальную строковую переменную.

написал код, но он увы зацикливается. Правильно ли я пытаюсь синхронизирывать потоки, зацикливание как я понимаю происходит в методе write, не могу додумать условие. спасибо за советы
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
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public string s=" ";
        static object locker = new object();
        public string put;
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog op = new OpenFileDialog();
            if (op.ShowDialog() == DialogResult.OK)
            {
                put = op.FileName;
                read();
                Parallel.Invoke(read, write);
            }
        }
 
        private void read()
        {
            StreamReader r = new StreamReader(put);
            while (true)
            {
                lock (locker)
                {
                    s = r.ReadLine();
                    if (s == null) break;
                    
                   
                }
            }            
        }
        private void write()
        {
            lock (locker)
            {
                
                while (true)
                {
                    lock (locker)
                    {
                        richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(s.ToUpper() + '\n'); }));
                       
                    }
                    if (s == null)
                        return;
                }
            }
        }
 
    }
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.02.2017, 20:45
Ответы с готовыми решениями:

Синхронизация двух потоков
Здравствуйте, в процессе обучения столкнулся с проблемой: У меня есть класс monitorfolder, который...

System.threading.timer и синхронизация двух потоков
Здравствуйте, в с# я совсем недавно и предо мной стоит следующая задача: сделать отображение...

Область видимости общей переменной для потоков + закрытие потоков
Есть два вопроса про потоки. Первый. Как можно сделать общую переменную для основного потока и...

Синхронизация двух потоков (мьютексы)
Задание звучит так: В программе порождаются два потока, работающие с одним файлом. Один поток...

4
608 / 583 / 157
Регистрация: 29.06.2010
Сообщений: 1,620
22.02.2017, 09:38 2
Лучший ответ Сообщение было отмечено max_1296 как решение

Решение

Цитата Сообщение от max_1296 Посмотреть сообщение
lock (locker) { while (true) { lock (locker) {
странная конструкция.

Цитата Сообщение от max_1296 Посмотреть сообщение
Правильно ли я пытаюсь синхронизирывать потоки, зацикливание как я понимаю происходит в методе write, не могу додумать условие
странно что там ошибок не происходит, выбрал первый подряд файл, так программе в методе write должена была null в ToUpper перевести, но зависла раньше) а всё почему? потому-что проверка на null после операции.

Я бы сделал по другому, организовал очередь строк, а не одну текущую строку (имеется в виду не строка как переменная, а строка как row текстового файла).

Метод Read накидывает в строку новых подстрок, Метод Write забирает самую первую строку и выводит её на экран.

И уже не по теме, но ради бога, поменяйте имя переменной в котором храниться имя файла. put - это что-то между push и pop сразу, так сказать, две операции над стеком в одном имени. Если что, путь по анлийски - path.

Добавлено через 27 минут
сверху: метод read выполняется дважды:
Цитата Сообщение от max_1296 Посмотреть сообщение
read();
Parallel.Invoke(read, write);
метод write, так как он описан сейчас, если всё произойдёт хорошо, уйдёт в вечный цикл при любом значении строки, отличной от null.

алгоритм адекватно будет работать только если предположить что методы read и write будут по очереди (строго по очереди) выполнять по одной иттерации из их циклов while. в принципе и к этому виду их можно привести, но тогда будут другие проверки, во первых метод read не должен ничего читать пока в переменной значение, отличное от null, во вторых метод write после отображения строки должен устанавливать её в null.

Добавлено через 30 минут
с минимальными изменениями ваш код:
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.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
 
namespace ReadFileTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public string s = null;
        static object locker = new object();
        public string put;
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog op = new OpenFileDialog();
            if (op.ShowDialog() == DialogResult.OK)
            {
                put = op.FileName;
 
                new System.Threading.Thread(read).Start();
                new System.Threading.Thread(write).Start();
            }
        }
 
        bool reading = false;
        private void read()
        {
            reading = true;
            StreamReader r = new StreamReader(put);
            while (!r.EndOfStream)
            {
                lock (locker)
                {
                    if (s == null)
                        s = r.ReadLine();
                }
            }
            reading = false;
        }
        private void write()
        {
            while (reading)
            {
                lock (locker)
                {
                    if (s != null)
                    {
                        Invoke(new MethodInvoker(AppendString));
                        s = null;
                    }
 
                }
            }
        }
        private void AppendString()
        {
            richTextBox1.AppendText(s.ToUpper() + '\n');
        }
    }
}
0
2 / 2 / 3
Регистрация: 19.08.2013
Сообщений: 100
22.02.2017, 09:53  [ТС] 3
Огромное спасибо. если не трудно можете показать как реализовать тоже самое с AutoResetEvent ?
0
608 / 583 / 157
Регистрация: 29.06.2010
Сообщений: 1,620
23.02.2017, 10:36 4
Цитата Сообщение от max_1296 Посмотреть сообщение
если не трудно можете показать как реализовать тоже самое с AutoResetEvent
нет))
0
0 / 0 / 0
Регистрация: 22.11.2017
Сообщений: 4
09.05.2018, 13:02 5
Извините, а что делать дальше? Программа запустилась, как теперь можно реализовать синхронизацию двух потоков?
0
09.05.2018, 13:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.05.2018, 13:02
Помогаю со студенческими работами здесь

Синхронизация двух потоков по общему ресурсу
Темы по поиску просматривал. Не помогло. Нужно синхронизировать два потока. Они просто должны...

Нужно ли синхронизировать доступ к переменной из двух потоков?
Допустим есть два потока: основной и вторичный. 1. И допустим есть глобальная переменная bool b;...

Синхронизация потоков на элементарном уровне (переключение потоков)
в общем разбираюсь с потоками, на сколько понял мне нужен lock Вот имеется просто пример ...

Синхронизация потоков: проблема гонки потоков
Есть проблема в синхронизации потоков, которую я не знаю, как решить. Точнее у меня получается...

Синхронизация потоков
Доброго дня, форум. столкнулся с данной проблемой: при пересоздании и перезапуске потока (которая,...

Синхронизация потоков
В общем идея была в том, что создаётся список потоков List<Thread> threads;. Все эти потоки...


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

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

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