Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.70/10: Рейтинг темы: голосов - 10, средняя оценка - 4.70
0 / 0 / 0
Регистрация: 04.11.2009
Сообщений: 23

Cоздание событий

11.04.2010, 00:31. Показов 2146. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
День добрый.
Вообщем изучаю .нет и сейчас параллельно выполняю курсовую работу в ней же. Возникла необходимость создания и обработки событий у собственного класса.
Схематически, всё это выглядит примерно так:
1. Создаётся экземпляр моего класса
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
    public delegate void PacketArriveEventHandler(object sender,CustomEventArgs c);
    public class CustomEventArgs : EventArgs
    {
        public CustomEventArgs(string s)
        {
            message = s;
        }
        private string message;
 
        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }
    class Class1
    {
        public event PacketArriveEventHandler PacketArrival;
        protected virtual void OnPacketArrival(CustomEventArgs e)
        {
            PacketArriveEventHandler handler = PacketArrival;
            if (handler != null)
            {
                e.Message += String.Format(" at {0}", DateTime.Now.ToString());
                handler(this, e);
            }
        }
 
        FileStream syncF;
        private Thread newThread;
        public Class1() //конструктор класса, создаёт текстовый файл и пишет в него строку
        {
            syncF = new FileStream("myTest.txt", FileMode.Create);
            byte[] bString = Encoding.ASCII.GetBytes("#D0=12*D1=32.3#");
            syncF.Write(bString, 0, bString.Length);
            syncF.Close();
        }
        private delegate void setArriveEvents(string s);
        private void setEvargs(string s)
        {
            OnPacketArrival(new CustomEventArgs(s));
        }
 
        public void startListening()
        {
            newThread = new Thread(new ThreadStart(this.reading));            
            newThread.Start();
        }
 
        private void reading()
        {
            //имитация работы - читаем файл, прочитанную строку передаём событию.
            while (true)
            {
                string s = "0";
                syncF = new FileStream("myTest.txt", FileMode.Open);
                syncF.Seek(0, SeekOrigin.Begin);    //начало потока
                byte[] bReadBuffer = new byte[syncF.Length - 1];
                syncF.Read(bReadBuffer, 0, Convert.ToInt32(syncF.Length - 1));
                s = Encoding.ASCII.GetString(bReadBuffer);
                syncF.Close();
                //Вот тут я решил считанную строку передать событию посредством делегата
                setArriveEvents SE = setEvargs; 
                SE(s + SE.Method.ToString());
                Thread.Sleep(100);
            }
        }
    }
А вот так я обращаюсь к классу из модуля формы:
C#
1
2
3
4
5
6
7
8
9
10
11
private void button1_Click(object sender, EventArgs e)
        {
            Class1 c = new Class1();
            c.PacketArrival += new PacketArriveEventHandler(c_PacketArrival);
            c.startListening();            
        }
 
        void c_PacketArrival(object sender, CustomEventArgs c)
        {
            textBox1.Text += c.Message;  //Вот тут возникает описанная ошибка
        }
Порылся по msdn, но пока ещё ничего не нашел подходящего.
Заранее спасибо
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.04.2010, 00:31
Ответы с готовыми решениями:

Cоздание формы
Как создать такую форму, что если она активна нельзя обращаться к каким-либо другим формам приложения?

Cоздание базы данных с нуля
нужно чтобы программа создавала базу данных на компе пользователя с нуля, то есть нажал он на кнопку, указал путь где создавать и всё...

Cоздание отчета word. Данные берутся из БД
Добрый день! Есть задача, необходимо реализовать отчет по нажатию на кнопку, есть бд(PostgreSQL), нужно выташить данные из таблицы `mans` и...

4
 Аватар для Mikant
1322 / 995 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
11.04.2010, 04:45
сразу признаюсь: код не читал - наверное, там все ок

в тот момент когда в этом бесконечном цикле происходит событие, естественно оно начинает обрабатываться в том же потоке, что и вызов. виндовый GUI работает только в одном потоке. при попытке изменить что-либо графическое из другого потока будет ругань и т.п. для нормального проброса данных (здесь - строки) между потоками они должны войти в единый контекст синхронизации. для этого посредством мьютексов они замораживаются и в этот момент можно передавать. у формы (у всех контролов) есть метод Invoke - надо юзать его и проблем не будет

вот разница

C#
1
2
3
4
5
6
7
8
9
10
11
private void SetTextBox1TextSafe(string s) {
            if (!InvokeRequired) // чтобы не вызывать Invoke без необходимости
                SetTextBox1TextUnsafe(s);
            else this.Invoke(new Action(SetTextBox1TextUnsafe), s);
        }
 
        private void SetTextBox1TextUnsafe(string s) {
            textBox1.Text = s;
        }
 
        private delegate void Action(string str);
зы. написано криво. повторять не рекомендую. но метод Invoke вызывается именно так
0
0 / 0 / 0
Регистрация: 04.11.2009
Сообщений: 23
11.04.2010, 12:11  [ТС]
Да,спасибо. про метод Invoke() я слышал. С тем, что ты описал я уже немного ознакомился и некоторое представление имею. Этот вариант я оставлю как запасной, если так и не найду выхода.
Моя ошибка, что я не пояснил, что я хочу избежать вот этого лишнего кода в модуле формы.
Я в бесконечном цикле моего класса сделал вот такое, но ошибка осталась:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        
        private delegate void setArriveEvents(string s);
        private void setEvargs(string s)
        {
            OnPacketArrival(new CustomEventArgs(s));
        }
        private void reading()  //работает в новом потоке
        {
            while (true)
            {
                ........................
                //Вот тут я решил вызвать событие посредством делегата
                setArriveEvents SE = setEvargs; 
                SE(s + SE.Method.ToString());
               ........................
            }
        }
Как мне вызывать обработчик события в основном потоке?
Чтобы не было вот таких конфликтов при попытке привязать параметры события к GUI?
0
 Аватар для Mikant
1322 / 995 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
12.04.2010, 02:17
вот сейчас я внимательно прочел всё - и все равно не понимаю, в чем же проблема. есть смутное подозрение, что ты не понимаешь, что такое обработчики событий и вообще делегаты. так вот, когда ты пишешь у события или у делегата += это значит, что когда он будет вызван, по цепочке будет вызвано просто еще несколько методов. очевидно, что пойдут они в том же потоке, что и вызов: нигде там никакой многопоточной магии не происходит. дам тебе рабочий код. уже хороший. старайся следовать ему.

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
using System;
using System.Threading;
using System.Windows.Forms;
 
namespace WindowsFormsApplication1 {
    static class Program {
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyForm());
        }
    }
 
    public class MyForm : Form {
 
        TextBox textBox = new TextBox();
 
        protected override void OnLoad(EventArgs ea) {
 
            MyClass mc = new MyClass();
 
            Action<string> SetText = new Action<string>(delegate(string s) {
                textBox.Text = s;
            });
 
            mc.TextReceived += delegate(object sender, TextDataReceivedEventArgs e) {
                this.Invoke(SetText, e.Text);
            };
 
            mc.StartCycleAsync();
 
            base.OnLoad(ea);
        }
 
        public MyForm() {
            SuspendLayout();
            this.Controls.Add(textBox);
            ResumeLayout();
        }
 
    }
 
    public delegate void Action();
    public delegate void Action<T>(T obj);
 
    public class MyClass {
 
        public event EventHandler<TextDataReceivedEventArgs> TextReceived;
 
        protected virtual void OnTextReceived(TextDataReceivedEventArgs e) {
            if (TextReceived != null)
                TextReceived(this, e);
        }
 
        public void StartCycleAsync() {
            new Action(delegate() {
                for (int i = 0; ; i++, Thread.Sleep(250))
                    OnTextReceived(new TextDataReceivedEventArgs(i.ToString()));
            }).BeginInvoke(null, null);
        }
 
    }
 
    public class TextDataReceivedEventArgs : EventArgs {
        private string _text;
        public string Text {
            get { return _text; }
        }
        public TextDataReceivedEventArgs(string text) {
            _text = text;
        }
    }
}
1
0 / 0 / 0
Регистрация: 04.11.2009
Сообщений: 23
12.04.2010, 12:32  [ТС]
Я как и говорил, только изучал это. То что я хотел нереализуемого, как я понял уже. Посмотрел пример библиотеки SharpPcap, где в отдельном потоке запускался цикл перехвата пакетов сети, а затем возникали события - там совершенно схожая с моей ситуация.
То есть задача получателя как раз прибегать к методу Invoke(), если есть необходимость.
Что такое обработчики событий и вообще делегаты я вполне уяснил себе.
Ладно, не буду изобретать черте-че, спасибо за подсказку
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.04.2010, 12:32
Помогаю со студенческими работами здесь

Cоздание файла на сервере,указывая урл.
Помогите с казалось бы простой проблемой,не успеваю разобраться,сорки поджимают. Необходимо на сервере создать файл,img,имя которого буду...

Cоздание собственной поисковой системы для ASP-сайта
Итересуюсь решениями создания собственной поисковой системы для ASP-сайта с массой статических страниц, которые нужно индексировать....

Cоздание отчета на основании математического расчета.
Добрый день. Посоветуйте как правильно подойти к решению задачи. Есть программа (мной написана). Она производит расчет. Нужно создать...

Cоздание двух событий
Задача: Напишите консольную программу, в которой программа просит ввести с клавиатуры любое число в диапазоне от 0 до 9. Если введено...

Реализовать хранилище событий, для хранения событий в БД
Доброго дня! Поставлена задача реализовать хранилище событий, для хранения событий в БД) Событие представляет собой обработанную...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru