Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.60/15: Рейтинг темы: голосов - 15, средняя оценка - 4.60
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
1

Ожидание изменения значения переменной

18.03.2016, 10:24. Просмотров 2838. Ответов 17
Метки нет (Все метки)

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

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

void method (int a) // вместо int a должна поступать наша переменная
{
something...
}

Добавлено через 30 минут
Да, с делегатами пытался разобраться.. пока все сложно.. Передаю данные из одного класса в другой
через:
C#
1
2
3
4
5
6
static class Data
{
    public static string Value { get; set; }
}
 
Data.Value = ... поступающие данные ...;
И принимаю их в другом классе через string str = Data.Value;
Как же отследить поступление в str новых данных?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.03.2016, 10:24
Ответы с готовыми решениями:

Ожидание потоком определенного значения переменной в другом потоке
Создать консольное приложение. В нем запускаются два независимых потока. Первый поток в цикле...

Отслеживание изменения значения переменной
Как мне сделать так, что бы при изменении переменной, выполнялась функция из другого класса и после...

Отслеживание изменения значения переменной
Привет! Возникла такая задача - есть адрес переменной в памяти какого-то процесса. Мне нужно...

Отследить изменения значения переменной
Допустим есть переменная static string str, как создать событие, или что-то вроде него, которое...

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

17
Storm23
Эксперт .NETАвтор FAQ
9201 / 4449 / 1617
Регистрация: 11.01.2015
Сообщений: 5,683
Записей в блоге: 34
18.03.2016, 10:31 2
Цитата Сообщение от qficer Посмотреть сообщение
Суть:
Нужно отслеживать поступление изменений в переменную после нажатия кнопки на протяжении длительного времени (делаю это таймером - уж очень глупо выглядит)
Для этого используются события. Замените поле на свойство и в сеттере вызывайте событие.

C#
1
2
3
4
5
6
7
8
9
10
11
            //где-то в коде:
            //подписываемся на событие
            Data.ValueChanged += Data_ValueChanged;
...
 
        private void Data_ValueChanged(object sender, EventArgs e)
        {
            //получаем измененные данные
            string str = Data.Value;
            //обрабытываем...
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    static class Data
    {
        public static EventHandler ValueChanged = delegate { };
        private static string _value;
 
        public static string Value
        {
            get { return _value; }
            set
            {
                _value = value;
                ValueChanged(null, EventArgs.Empty);
            }
        }
    }
1
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 10:59  [ТС] 3
Сейчас испробую )

Добавлено через 20 минут
Выдает ошибку:
Имя "Data_valueChaged" отсутствует в текущем контексте (CS0103)

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
static class SomeClass // Отсюда беру данные
{
    public static string SomeMethod(string text)
        {
            ...
            Data.ValueChanged += Data_ValueChanged;
            ...
        }
}
 
static class Data
{
    public static EventHandler ValueChanged = delegate { };
    private static string _value;
 
    public static string Value
    {
        get { return _value; }
        set
        {
            _value = value;
            ValueChanged(null, EventArgs.Empty);
        }
    }
}
public partial class MainForm : Form //Сюда вывожу
{
    public void Data_valueChaged(object sender, EventArgs e)
    {
        label1.Text = Data.Value;
    }
}
0
Даценд
Модератор
Эксперт .NET
5041 / 4299 / 2795
Регистрация: 20.04.2015
Сообщений: 7,757
18.03.2016, 11:22 4
qficer,
Немного не так.

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
static class SomeClass // Отсюда беру данные
{
    public static EventHandler ValueChanged = delegate { };
    private static string _value;
 
    public static string Value
    {
        get { return _value; }
        set
        {
            _value = value;
            ValueChanged(null, EventArgs.Empty);
        }
    }
}
 
public partial class MainForm : Form
{
 
    public Form1()
    {
        InitializeComponent();
        SomeClass.ValueChanged += Data_ValueChanged;
    }
 
 
    public void Data_ValueChanged(object sender, EventArgs e)
    {
        label1.Text = SomeClass.Value;
    }
 
}
2
18.03.2016, 11:22
Psilon
Master of Orion
Эксперт .NET
6039 / 4893 / 903
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
18.03.2016, 11:25 5
Storm23, только в ValueChanged лучше this передавать, а не null все же. Да и EventArgs имело смысл сделать сразу с передачей нового значения.
2
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 11:40  [ТС] 6
Благодарю за отзывы! Сейчас попробую

Добавлено через 8 минут
Даценд, подскажите, где же точка входа? Где переменная, значение которой будет передаваться? У меня создан метод и не понятно как внедрить в него этот код, поясните, пожалуйста?
Psilon, поясните, пожалуйста?
0
Даценд
Модератор
Эксперт .NET
5041 / 4299 / 2795
Регистрация: 20.04.2015
Сообщений: 7,757
18.03.2016, 12:09 7
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
static class SomeClass // Отсюда беру данные
{
    public static EventHandler ValueChanged = delegate { };
    private static string _value; //отслеживается значение этой переменной
 
    public static string Value //связанной со свойством
    {
        get { return _value; }
        set
        {
            _value = value;
            ValueChanged(null, EventArgs.Empty); //в котором при изменении значения переменной вызывается метод, подписанный к событию
        }
    }
}
 
public partial class MainForm : Form
{
 
    public Form1()
    {
        InitializeComponent();
        SomeClass.ValueChanged += Data_ValueChanged; //подписываем метод к событию
    }
 
 
    public void Data_ValueChanged(object sender, EventArgs e) //этот метод будет вызываться при изменении переменной в классе SomeClass
    {
        label1.Text = SomeClass.Value;
    }
 
}
1
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 12:18  [ТС] 8
Отчаянно благодарю ))
Сейчас попробую реализовать.
0
Psilon
Master of Orion
Эксперт .NET
6039 / 4893 / 903
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
18.03.2016, 12:24 9
qficer, передавать нуллы вообще плохая практика. Настолько плохая, что в новой версии языка вводят специальные типа: not-null reference. Гораздо полезнее было бы передать текущий объект.
1
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 13:06  [ТС] 10
Даценд, Не работает. Добавляю в метод
Цитата Сообщение от Даценд Посмотреть сообщение
public void Data_ValueChanged(object sender, EventArgs e)
MessageBox.Show("OK!");, но сообщение не выходит, да и label не меняется. Пробовал добавлять в TextBox.Text, так же не выходит. Проверил, приходят-ли значения в начальную переменную - приходят. Просто не понимаю почему не работает

Psilon, Поясните о чем речь? Что есть передавать null? Как можно решить проблему передачи минимальным и понятным кодом? Могу я вызвать метод класса Main из static class SomeClass, при поступлении данных в переменную метода SomeClass?

Добавлено через 2 минуты
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
static class SomeClass // Отсюда беру данные
{
    public static EventHandler ValueChanged = delegate { };
    private static string _value; //отслеживается значение этой переменной
 
    public static string Value //связанной со свойством
    {
        get { return _value; }
        set
        {
            _value = value;
            ValueChanged(null, EventArgs.Empty); //в котором при изменении значения переменной вызывается метод, подписанный к событию
        }
    }
 
    ... somemethod...
        {
            _value = str;
        }
 
}
 
public partial class MainForm : Form
{
 
    public Form1()
    {
        InitializeComponent();
        SomeClass.ValueChanged += Data_ValueChanged; //подписываем метод к событию
    }
 
 
    public void Data_ValueChanged(object sender, EventArgs e) //этот метод будет вызываться при изменении переменной в классе SomeClass
    {
        label1.Text = SomeClass.Value;
        MessageBox.Show("OK!");
    }
 
}
0
Psilon
Master of Orion
Эксперт .NET
6039 / 4893 / 903
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
18.03.2016, 13:18 11
qficer, когда вызывается событие, там передается null, если видите. Хотя класс статичский, что я изначально пропустил. Но статические события вообще редко используются. А общей практикой передавать this (в случае статики можно было бы передавать новое значение):
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
    public partial class Form1 : Form
    {
        private MyClass myClass = new MyClass();
        public Form1()
        {
            InitializeComponent();
            myClass.TextChanged += (sender, args) => MessageBox.Show("New text is: " + ((MyClass) sender).Text);
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            myClass.Text = Guid.NewGuid().ToString();
        }
    }
 
    class MyClass
    {
        public EventHandler TextChanged = delegate { };
        private string _text;
 
        public string Text
        {
            get { return _text; }
            set
            {
                _text = value; 
                TextChanged(this, EventArgs.Empty);
            }
        }
    }
1
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 13:53  [ТС] 12
Правильно я понимаю?
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
    class MyClass
    {
        public EventHandler TextChanged = delegate { }; // Объявляем то, чем будем передавать из класса в класс
        private string _text; // создаем переменную с типом string
 
        public string Text // создаем конструктор, который при передаче значения переменной _text будет пересылать
                                // ее туда, в другой метод другого класса
        {
            get { return _text; }
            set
            {
                _text = value; 
                TextChanged(this, EventArgs.Empty);
            }
        }
    }
 
public partial class Form1 : Form // Это, конечно, класс с формой
    {
        private MyClass myClass = new MyClass(); // Создаем объект класса из которого ждем значение
        public Form1()
        {
            InitializeComponent();
                                                             // Это некая лямбда, которая... выводит текстовое значение "sender"
                                                             // в бокс. Значение sender, видимо, приходит из... каша в голове
            myClass.TextChanged += (sender, args) => MessageBox.Show("New text is: " + ((MyClass) sender).Text); 
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            myClass.Text = Guid.NewGuid().ToString(); // Это в принципе не понятно.. что есть Guid.NewGuid().?
        }
    }
Добавлено через 15 минут
Уважаемый Даценд, "добейте" тему, пожалуйста
Может проблема в том, что класс static?
Как я понимаю вся суть в объявлении EventHandler, который вызывает метод из другого класса?
Но если передать из статичного класса в другой (Main) с помощью:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
static class Data
{
    public static string Value { get; set; }
}

и уже в классе Main обработать с помощью EventHandler? Подскажите, как обработать ожидание переменной внутри одного класса? Это решит проблему
0
Psilon
Master of Orion
Эксперт .NET
6039 / 4893 / 903
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
18.03.2016, 13:55 13
Лучший ответ Сообщение было отмечено qficer как решение

Решение

qficer, не совсем. Начиная сверху вниз:
объявляем событие. При вызове события будут вызваны все подписчики (в нашем случае - лямбда из формы).
Дальше объявляем полное свойство. Бывают Авто-свойства public int X {get; set;}, а бывают полные - где мы все сами пишем. Т.к. нам нужен контроль над записыванием в переменную, делаем полное свойство и описываем, что после изменения вызывается событие.

Затем в конструкторе формы подписываем собственно нашу лямбду. Выводим мессадж бокс с сообщением. Гуид просто генерирует случайную строку, не более того. Можно вместо него "123" написать с тем же успехом.

Ну а затем запускаем. И смотрим что происходит.

Нажимаем на кнопку. Кнопка изменяет свойство Text. Из-за изменения свойства вызывается событие TextChanged. Так как на событие есть подписчик - лямбда из формы - вызывается она, и показывается мессадж бокс. Конец истории.
1
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 13:57  [ТС] 14
Psilon, подскажите, как обработать ожидание переменной внутри одного класса? Может есть решение с меньшим количеством кода ?
0
Psilon
Master of Orion
Эксперт .NET
6039 / 4893 / 903
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
18.03.2016, 14:00 15
qficer, что значит ожидание переменной?

Добавлено через 2 минуты
Опишите подробно, что вам нужно и где вы собираетесь это применять.
0
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 14:06  [ТС] 16
Psilon, Подписка на событие

Добавлено через 5 минут
Цитата Сообщение от Psilon Посмотреть сообщение
Опишите подробно, что вам нужно и где вы собираетесь это применять.
__________________
Изучаю (самостоятельно) язык, потому не столь важна сама программа, но важно понимание сути. Суть делегата я понял, но реализацию пока усваиваю. Для лучшего понимания сути вызова метода при изменении отслеживаемого события и хочу написать пробную программу, которая будет получать данные в одном классе, а выдавать в другом и отлавливая факт записи в переменную, будет в тот же момент выдавать данные в какой-либо элемент визуализации.
0
Psilon
Master of Orion
Эксперт .NET
6039 / 4893 / 903
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
18.03.2016, 14:35 17
Лучший ответ Сообщение было отмечено qficer как решение

Решение

qficer, я бы на вашем месте просто сделал напоминалку. Я в свое время такое писал как лабу. То есть у пользователя есть список напоминаний, он может их добавлять/удалять. При наступлении события должно вызываться событие EventHappened, или что-то в таком духе.

Причем желательно сделать в виде трех модулей: один модуль с самим нотификатором, и две вьюхи - консольное приложение, которое пишет в консоль, и графическое приложение, которое пополняет textbox логами, что где было вызвано (или мессаджбокс вызывает). Это чтобы не было желания вызывать мессажбокс напрямую из класса, который заведует уведомлениями

Что касается реализации, мне помогает понимать та мысль, что делегат - это просто умный указатель на функцию (точнее, на много функций). То есть Мы можем написать
C#
1
int result = Foo(10);
А можем сначала сохранить указатель на метод в переменную, а только потом вызвать:
C#
1
2
Func<int, int> foo = Foo;
int result = foo(10);
Нужно понимать, что функции - это тоже переменные, которые можно присваивать, складывать и т.п. (правда вычитать и делить нельзя ). И когда для работы с переменными используются обычные типы - инты всякие и строки, то при работе с функциями как с переменными используется специальный функциональный тип, который в шарпе имеет имя "делегат".

Ну а событие, это самый обычный делегат, который правда на уровне компиляции проверяется специальным образом (событие может вызывать только класс, в котором он объявлен, а вот делегат можнт вызвать кто угодно, это ведь просто указатель на функцию, и все в таком духе), но для рантайма является самым обычным.
1
qficer
8 / 8 / 4
Регистрация: 09.10.2015
Сообщений: 37
18.03.2016, 15:45  [ТС] 18
Спасибо за разъяснения! Доступно и простым языком - это именно то, что я искал.
Теперь понятно, что есть делегат.
0
18.03.2016, 15:45
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.03.2016, 15:45

Как присвоить значение переменной, исходя из значения другой переменной?
Всем привет. Нужна помощь. Есть переменная, например &quot;month&quot; которая может принимать значения...

Отслеживание изменения переменной
Здравствуйте! Вопрос немного ламерский. Есть trackBar. Есть значение переменной, допустим, а....

Ограничение диапазона изменения переменной
Есть интервал допустим 70. Как в коде поставить чтоб он не превышал 70! только 70 не больше


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru