Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.61/146: Рейтинг темы: голосов - 146, средняя оценка - 4.61
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84

Ожидание события. Как правильно?

22.09.2015, 23:56. Показов 29993. Ответов 43
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.
Язык C#. (Проект не помню точно как создавал. Но что-то по умолчанию с формами и без излишеств.)
Есть одна форма. На неё добавлены 3 элемента: Кнопка, COMпорт и таймер.
По нажатию на кнопку запускается некая функция (попутно запускается таймер и предполагается что по COMпорту что-то может прийти). И вот в процессе выполнения этой функции надо поставить её на паузу до тех пор пока либо таймер не сработает либо байт с порта не прийдёт. Сделал я вот таким способм.

Кусок этой самой функции, там где она собственно должна быть на паузе.
C#
1
2
3
4
5
6
7
8
9
10
.....
IsAnswered=false;
OutOfTime = false;
this.timer1.Enabled = true;
this.timer1.Start();
while ((!OutOfTime) && (!IsAnswered))
 {
     Application.DoEvents();//Ждём ответа.
 }
.....

И Также есть обработчики таймера и порта.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  private void timer1_Tick(object sender, EventArgs e)
        {
            this.timer1.Stop();
            this.timer1.Enabled = false;
            OutOfTime = true;
        }
 
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            int CurByte;
 
            this.timer1.Stop();
            this.timer1.Enabled = false;
            OutOfTime = false;
            IsAnswered = true;
        }
И всё вроде хорошо работает. Но цикл вместо спячки?!...Ну это както совсем не правильно. А вот как Правильно сделать? )
Что-то вроде
C++
1
2
3
4
HANDLE waitArray[2] = {event1, event2};
DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE); //вместо цикла
//и 
SetEvent(event1);//в обработчике таймера и порта
можно на C# сделать? Но только без импорта дллелек... А как-то C#-ким методом.

Спасибо за внимание.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
22.09.2015, 23:56
Ответы с готовыми решениями:

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

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

Сделать ожидание события клика на программно созданных pictureBox
Как сделать ожидание события клика на программно созданных pictureBox? Пробовал через Sleep, но он подгружает программу, не кликнуть, не...

43
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
01.10.2015, 00:09
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от insite2012 Посмотреть сообщение
Я раньше делал на отдельных потоках, естественно код разрастался (свои события для того, второго, третьего...), а тут все в одном флаконе.
Ну от своих событий все одно не избавишься в большинстве случаев Если всю информацию для довольно сложного UI запихать в ProgressChanged, а потом парсить параметры, то в конце-концов код станет малопонятным. Но для задач попроще, вроде той, что в данной теме-самое то.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
01.10.2015, 04:27  [ТС]
))) Я тут пока в ваших примерах разбираться буду .... вы не могли бы сказать:почему вы применили конструкции get set using. Вот почему именно с ними а не как то иначе? И кстати. SerialPort можно и не добовлять вручную он вобщемто как кнопка или текст бокс в контролах есть...Зачем вы его руками добавляли?
И честно говоря я до конца не понял в чём конкретное значение асинхронный и синхронны? По идее есть 2 определения почти противоположных.
1.Первое это одновременно и не одновременно. Работать синхронно значит одновременно. Асинхронно - сначала один потом другой, или в разнобой...Ну как прыжки в воду например.
2.Второе это когда 2 процесса тактируются от какого-то генератора (или события или ещё чего). Тогда Синхронность не озночает одновременное выполнение, но и не противроечит ему. Тоесть события могут быть синхронными но в противофазе.
Что обычно имеют в виду в описаниях, когда упоминают про Синхронный и Асинхронный? )) Что-то вроде по очереди и одновременно?

Добавлено через 4 минуты
А, да. Я ещё раз переспрошу. Что происходит с теми переменными которые "в скобках" под локом? Они тоже переходят в разряд тех что нельзя трогать? И можно ли как то узнать из другого потока под локом переменная сейчас или нет?
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
01.10.2015, 07:38
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
get set
Ими описывается свойство. По сути это 2 метода, get{} выполняется, когда свойство читают, set{} - когда присваивают ему значение.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
using
Это то же самое, что создать какой-то объект, а потом вызывать для него Dispose(). Работает через интерфейс IDisposable. Когда код выходит из этого блока, Dispose() автоматически вызывается. Не весь мусор может собрать сборщик-некоторые низкоуровневые ресусрсы нужно освобождать вручную, в этом методе они и освобождаются.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Синхронный и Асинхронный
В данном случае Синхронно-значит подряд. Одна часть кода выполнилась-потом другая, и не иначе. Асинхронно-это когда код ставит какую-то задачу выполняться и идет дальше, а та задача тем временем выполняется параллельно. Когда такая задача выполнилась-она сообщает об этом. В языке это реализовано в первую очередь виде класса Task и ключевых слов async/await, пример с которыми я давал в 1ом своем посте в этой теме,так же у многих стандартных классов есть асинхронные методы. Один из таких-BeginInvoke у класса Control.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
А, да. Я ещё раз переспрошу. Что происходит с теми переменными которые "в скобках" под локом? Они тоже переходят в разряд тех что нельзя трогать?
С теми, которые в таких {} скобках ничего не происходит. Это касается только объекта, который в таких () скобках.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
И кстати. SerialPort можно и не добовлять вручную он вобщемто как кнопка или текст бокс в контролах есть...Зачем вы его руками добавляли?
Так он же не должен быть в классе формы по условию-зачем его туда добавлять-то? Кроме того ,даже если бы было не так, то для наглядности все одно стоило так сделать. Не пихать же сюда Designer.cs.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
05.10.2015, 12:58  [ТС]
Ребят, я не пропал и не забил. Я думаю Когда обработаю всё то, что вы сказаи и решу, что мне больше понравилось я сообщу об этом.
Пока же я ещё хотел спросить.
Предположим у нас есть 2 созданных нами потока (помимо основного потока программы). В этих потоках запущены функции с вечным циклом и с EventWaitHandle внутри цикла. Получаем 2 потока которые тихо мирно спят и никого не загружают пока не получат извещение о произошедшем событии(событиях). Мы можем завести ещё переменную в которой будет храниться некоторое число; при отправки событий для текущего потока будет ещё и переменная эта отправляться(менятся). А эта переменная будет через switch case использоваться внутри цикла после EventWaitHandle чтоб выбирать чтож конеретно должен делать поток который мы решили разбудить.
Ну классика жеж вроде. Всё понятно вроде.. всё удобно...
Теперь вопрос ) А как можно добавить подобное в поток формы? ..Куда и киким синтаксисом? ... Вот есть у нас функции обработчики события контролов таймеров и прочего которые в классе формы есть. Они выполняются тогда, когда происходит событие. И есть в описании класса нашей формы напрример вот такие строки
C#
1
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
Тоесть тут мы прривязываем this.Form1_FormClosing к событию закрытия. По идее событие закрытия this.FormClosing мы вобще говоря не определяли САМИ - оно уже кем-то гдето-то по умолчанию для всех форм есть (мыж именно от этих самых "всех форм" и унаследуем нашу конкретную форму всегда...). А как можно для нашей конкретной формы добавить событие this.MySpecialEvent. Которое каким-то (вот каким?! как?) образом будет генерироваться в другом потоке и через прописанную нами вручную строкой
C#
1
this.MySpecialEvent+= ... бла бла бла (Form1_MySpecialEventMyFunction)
вызывать исполнение Form1_MySpecialEventMyFunction именно уже в потоке формы?
Пппонятно спросил? )))

Добавлено через 8 минут
В простых C++ было всё просто с этим.
C++
1
2
3
4
5
6
7
8
9
//Заводили своё сообщение.
#define        WM_COMPLETEMY     (WM_USER + 0)
//Откуда угодно слали его
PostMessage (TargetHWND, WM_COMPLETEMY,0,3);
//И потом тут оно просто обрабатывалось
INT_PTR CALLBACK WndProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch( uMsg )
    {
Это я ещё раз тоже самое спрашиваю ).. Вот такое в С# как для формы сделать?

Добавлено через 58 минут
Вобщем-то у вас в примерах похоже именно это и было реализовано.Если не ошибасюь. Можно подробнее про этот момент?
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
05.10.2015, 19:01
PostMessage и WndProc кстати в шарпе можно использовать точно так же, у формы запросто можно переопределить WndProc через override. Все WinApi спокойно можно использовать, только придется каждую функцию сначала импортировать как указано на сайте pinvoke.net. Но в данном случае тут нет нужды для таких извращений. В примерах выше собственное событие реализовано только в моем варианте, у insite2012 вместо этого используется событие воркера.
C#
1
2
        public event DataRecivedEventHandler DataFromComPortRecived;
        public delegate void DataRecivedEventHandler(object sender, string data);
Вот тут оно объявлено, дальше по тексту видно, как оно используется. Если что-то непонятно-уточняйте

Добавлено через 18 минут
Вот тут можно про события глянуть.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
06.10.2015, 16:49  [ТС]
Думал можно с помощью событий избежать инвоков.. но вот нерабочий код...
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
 
 
namespace COMtestCshr
{
    public partial class Form1 : Form
    {
        private Thread MyMainThread;
        private MyMainClass MyMainClassExmpl;
        private String LabelStr;
 
        public Form1()
        {
            InitializeComponent();
            LabelStr = " ";
            StartMainThread();
        }
 
        private void StartMainThread()
        {
            //Thread MyMainThread = new Thread(new ThreadStart(MainThreadInitFunc));
            MyMainThread = new Thread(MainThreadInitFunc);
            MyMainThread.IsBackground = true;
            MyMainThread.Name = "CAMAC1MainThread";
            MyMainThread.Start();
        }
        private void MainThreadInitFunc()
        {
            MyMainClassExmpl = new MyMainClass(this);
            MyMainClassExmpl.MyMainClassEvent += new MyMainClass.MyMainClassEventHandler(EventWorker);
            MyMainClassExmpl.MyMainF();
        }
 
        void EventWorker(object sender, EventArgs eventArgs)
        {
            LabelStr = "sdf";
           // this.labelDeviceStatus0.Text = LabelStr;
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            MyMainClassExmpl.IsEnd = true;
             while (!MyMainClassExmpl.IsFinished)
              {   
                 Application.DoEvents();
              }
            // MyMainThread.Abort();
        }
 
 
        private void buttonSend1_Click(object sender, EventArgs e)
        {
 
            this.labelDeviceStatus0.Text = LabelStr;
        }
 
    }
 
    public class MyMainClass
    {
        private Form1 UserForm1;
 
        public Int64 i;
        public bool IsEnd;
        public bool IsFinished;
 
        public event MyMainClassEventHandler MyMainClassEvent;
        public delegate void MyMainClassEventHandler(object sender, EventArgs eventArgs);
 
        public MyMainClass(Form1 UserForm1In)
        {
            UserForm1 = UserForm1In;
            MyMainClassInit();
        }
        private void MyMainClassInit()
        {
            IsEnd = false;
            IsFinished = false;
            i = 0;
        }
 
        public void MyMainF()
        {
            while (!IsEnd)
            {
                i++;
                EventArgs eventArgs = new EventArgs();
                MyMainClassEvent(this, eventArgs);
                Thread.Sleep(100);
            }
            IsFinished = true;
        }
 
    }
 
 
}
Точнее этот код работает. Текст меняется по нажатию на кнопку. а вот если прям в EventWorker засунуть, изменение текста, то сосбвтенно вылетает ошибка о том что доступ контрола не из того потока. Ну это прям совсем уже не прилично. Какое форме дело до того откуда событие пришло?! Пришло и всё! - Обрабатывай ).. Но нет... Вроде ж просто сообщение хотел отправить форме о некотором событии и хотел чтобы форма на него реагировала.. как на таймер или нажатие кнопки... Выходит нельзя чтоли "абстрактное" событие послать форме и научить её его обрабатывать?! ... Или я чёт не так делаю? PostMessage вроде же без таких вот закидонов был... А если я вобще надумаю из другого процесса или другой программы в форму что-то отправить? Вобще будет без шансов?

Кстати ради эксперимента попробовал завести string переменную.. или как оно там называется вобщем с get set, и в set засунуть вывод полученной строки на форму. А изменять эту переменную я пробовал в другом потоке... Ну вобщем результат тот же - ошибка про доступ контрорла из другого потока.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
06.10.2015, 21:54
Ну так а чем вам так не нравятся инвоки? Винформы так устроены, что к тамошним контролам нельзя напрямую получить доступ из другого потока, а обработчик события выполняется в том же потоке, в каком событие произошло, что логично. Инвоки же позволяют влезть из одного потока в другой и там выполнить какой-то код, что решает проблему. В некоторых случаях альтернатива потокам-асинхронное программирование(пример по ссылке в моем первом посте в этой теме). PostMessage же-это WinApi для окон, оно не имеет прямого отношения к какому-либо языку и работа его обеспечивается ОС, если вам удобно им пользоваться-никто не запрещает Но им можно посылать сообщения только окну, а через event обеспечивается удобное взаимодействие между любыми классами. PostMessage в большинстве случаев логично использовать для управления чужим приложением, а не своим.
Про get и set - прочитайте про свойства поподробнее, к потокам это не имеет никакого отношения... Это сделано в первую очередь для инкапсуляции.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
07.10.2015, 04:36  [ТС]
Про get и set - прочитайте про свойства поподробнее, к потокам это не имеет никакого отношения... Это сделано в первую очередь для инкапсуляции.
Это только ради экспериментов, я особо и не надеялся.
Но вот
, а обработчик события выполняется в том же потоке, в каком событие произошло, что логично.
это согласен, логично... к сожалению. Мы же посути через event вызываем по ссылке на функцию исполнение какогото куска когда из другого места. И вобщем-то да.. логично что он исполняется там где его вызвали... Хотя если подписчиков несколько и они в разных потоках, и если они устроены так, что имеют очередь обработки событий, которую обрабатывают, а в остальное время спят, .. то тогда был бы хорошо иметь возможность заставить реагировать их самих в своих потоках на это событие в порядке очереди. Казалось бы должен быть како-то способ так делать...?! И не обязательно подписчиком должна быть форма, лишь бы очередь была, спячка когда бездействие, и функция обработки события.. Ну или на крайняк заслать прерывание в другой поток и передать тому потоку указатель на функцию к исполнению.

Добавлено через 1 минуту
Хотя ... лучше в очередь всё же ставить, чем прерывать исполнение...

Добавлено через 5 минут
Есть у нас 2 микроконтроллера, которые ногами между собой связаны... или память внешнюю имеют общую...Мы же можем когда захотим дернуть ногой одного микроконтроллера, разбудить или вызвать прерывание другого и заставить его на это отреагировать... Исполняемый код конечно можно второму передать, указав на кусок кода в общей памяти. Это да, вариант, который может и пригодиться в какихто случаях. НО в большинстве случаев горадздо проще и быстрее и логичнее и рациональнее и вабще.. просто сразу написать код для второго микроконтроллера для обработки события дергания его за ногу.

Добавлено через 21 секунду
Это просто для аналогии с тем что бы мне хотелось....
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
08.10.2015, 10:52  [ТС]
Ну вот как так то... и Task и BackgroundWorker и просто запуск чего-то в рукотворном потоке... так много вариантов по сути почти одного и того же. А возможности в самый широкоиспользуемый поток Form'ы добавить подпись на наше рукотворное событие... чтобы действительно в очередь формы попадало и в форме делалось а не абы где... нету? PostMessage и всё? (( Грусть тоска печаль...
Можно конечно просто переменную в форму слать и там по таймеру её просматривать...Может это и нормально... кто его знает как там на самом деле происходят обработки событий контролов в форме... может планировщик по таймеру проглядывает пришло что новое ЭТОЙ форме или нет... Не лишено смысла... Но как-то не верится в такое...

Добавлено через 1 минуту
Так.. а PostMessage в C# есть вобще? Или его через импорт длл надо?
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
10.10.2015, 10:53  [ТС]
Если тут комуто ещё интересно, то вот.
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
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
 
namespace FormsBackground
{
    public partial class Form1 : Form
    {
        private Thread MyMainThread;
 
        static AutoResetEvent ForBGWorkerEvent;
        private bool ISBGworkerRuning;
        private bool ISMyMainFRuning;
        private bool ISMyMainFFinished;
        private Int64 SomeData;
        public Form1()
        {
            InitializeComponent();
 
            SomeData = 0;
            
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
            if (backgroundWorker1.IsBusy != true)
            {
                // Start the asynchronous operation.
                ISBGworkerRuning = true;
                backgroundWorker1.RunWorkerAsync();
            }
 
            ForBGWorkerEvent = new AutoResetEvent(false);
 
            MyMainThread = new Thread(MyMainF);
            MyMainThread.IsBackground = true;
            MyMainThread.Name = "CAMAC1MainThread";
            ISMyMainFRuning = true;
            MyMainThread.Start();
 
        }
        public void MyMainF()
        {
            while (ISMyMainFRuning)
            {
                Thread.Sleep(100);
                ForBGWorkerEvent.Set();
            }
            ISMyMainFFinished = true;
        }
 
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
 
            while (ISBGworkerRuning)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    ISBGworkerRuning = false;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    //System.Threading.Thread.Sleep(100);
                    ForBGWorkerEvent.WaitOne();
                    worker.ReportProgress(0);
                }
            }
        }
 
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                this.label1.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                this.label1.Text = "Error: " + e.Error.Message;
            }
            else
            {
                this.label1.Text = "Done!";
            }
        }
 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            SomeData++;
            this.label1.Text = SomeData.ToString();
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = SomeData.ToString();
        }
    }
}
Вобщем можно слать в форму событие. Нормальное "Событие", а не event... И ЖДАТЬ СОБЫТИЕ соответсвтенно тоже можно. Собственно backgroundWorker этим и может заниматься. Добавляем его на форму, и внутри его делаем WaitOne, после чего добавляем ReportProgress(), которое уже генерит событие в форму и там его уже можно обрабатывать. Invoke в backgroundWorker не нужен, поэтому можно и без ReportProgress прям в DoWork (backgroundWorker1_DoWork) делать всё что нужно. Зачем всё это? А что-бы можно было куданить засунуть возможность ожидания события от другого потока без PostMessage и event. PostMessage без ImportDLL не работает, а event... это вобще обман сплошной, ибо выполняется он всёравно там где вызван. А ежели мы хотим именно в ином потокое относительно генератора некоторого события выполнять код, то вот тока либо PostMessage либо как я описал...
Ежели чё не так, поправте, пожалуйста.

Добавлено через 53 секунды
А. за пример кода прошу прощения, он местами избыточный - это мой результат экспериментов и копипасты мсдн.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
11.10.2015, 01:40
Какое-то время не смотрел тему... Воркер-это обертка над тем же потоком, суть от этого не сильно изменяется. Инвоков там не нужно писать только потому, что они происходят внутри. Как подождать в потоке-в теме уже предложили 2 варианта-либо EventWaitHandle(или его наследники,как в вашем случае), либо использовать вместо потоков асинхронность. Если есть желание - ничто не мешает оформить все это в виде очереди сообщений, создать эту самую очередь и при добавлении элемента будить поток, а когда все сообщения обработаны-опять его усыплять. В вашем же коде потоков 3 и все в одном классе, что не соответствует поставленной задаче.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
PostMessage без ImportDLL не работает
Что же мешает написать этот самый импорт?
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
а event... это вобще обман сплошной
Это говорит лишь о том, что вы не понимаете, как его использовать. К потокам event не имеет никакого отношения-это для эффективной передачи данных между классами.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
чтобы действительно в очередь формы попадало и в форме делалось а не абы где...
Опять же-эта задача элементарно решается инвоками... чего вы их так невзлюбили-совершенно не понимаю
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Task
Это не совсем обычный поток. Это задача, какая выполняется в потоке из ThreadPool(про различие), классический поток-это Thread.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
11.10.2015, 08:19  [ТС]
Как я уже говорил, по хорошему надо чтобы программа была в одном потоке, а форма в другом и что бы они были по максимуму независимы. Форма нужна только чтобы не в консоль выводить какието сообщения, данные и прочее что навычисляет программа, ну и чтобы считывать какието данные от пользователя. В форму допустимо засунуть функции для проверки вводимых данных от пользователя и преобразования в удобочитаемый формат того чтобы выдаст основная программа. Можно ещё добавить в форму что-то что явно независимо от всей остальной программы может происходить. Например если музыкальный проигрыватель делать. В основном потоке всё будет насчитываться и отправляться в буфера аудо устройств. А вот в форму можно добавить плей-лист. Форма может проверять файлы на правильный формат, удалять или добавлять в список новые треки. А слать она будет уже тока сообщения в главный поток о том что пользовтель тыкнул плей и сказать что же именно он захотел просулашать. Писать же весь код в обработчиках события формы это может и можно... но как-то очень не правильно, просто в силу того что UI и основной код в одном месте при разрастании обоих превращается в жуткого неповоротливого монстра.
PostMessage в C# в явном виде я не нашел.. Чему был очень удивлён. Но PostMessage всё же штука специализированная, заточенная под окна. WaitHandle же более универсален. Более того он не только межпотоковый но и межпроцессовый может быть. PostMessage конечно тоже межпотоковый, но через WaitHandle можно и не только с окнами работать. Хотя.. если покопаться то возможно получится что PostMessage на WaitHandle или чем-то подобном реализован.
В моём примере не совсем 3 потока. Поток формы - раз. Поток (а точнее пул потоков) BGworkera - два. А третий это поток в котором делается основной код и который взаимодействует с формой самым минимальным и необходимым образом. Нет смысла код засовывать в BGworker по причине которую я уже описал выше - хорошо всё таки код и UI разделять по максимуму.

Invoke не смертельно конечно. Кроме одного НО. Он возникает только в том случе, когда мы пытаемся напрямую достучаться до контролов из другого потока. А это явный признак того что UI и основной код программы не полностью разделены. Вот когда мы используем делегаты, то мы код, который должен быть по идее в потоке UI, начинаем исполнять в потоке основного кода программы, вот тогда и возникает необходимость инвоков. Тоесть инвоки это не проблемма. Проблемма это наличие причины по которой эти инвоки надо использовать.

event это что называется трудности перевода.
Event wait handles are not events in the sense usually meant by that word in the .NET Framework. There are no delegates or event handlers involved. The word "event" is used to describe them because they have traditionally been referred to as operating-system events, and because the act of signaling the wait handle indicates to waiting threads that an event has occurred.
https://msdn.microsoft.com/en-... English%29
Вобщем event он дейтсвительно вовсе не для ГЕНЕРАЦИИ и ЧТЕНИЯ событий нужны. И тут явно путаница возникает, так как event к реальным событиям отношения не имеет. Это виртуальный обман. Подписываемся в одном месте, вызываем в другом и кажется что один вызвал "событие" а второй на него отреагировал... По сути же вызывает и раегирует одни и тотже, но правда то что он делает вовсе не его работа). Да , для взаимодействия между классами это может и нужно. Но к раельным события этом не имеет никакого отношения. А то что назвали event'ом ... ну я даже неа знаю как это объянсить.. это прям диверсия и вредительство.

А что касается Task то принципиального различия нет - это тоже просто другой поток. Разница лишь в том как оно создается, поддерживается и убивается. BGworker тоже например пул а не просто поток.

Но собственно почему BGworker? Дело не в том, что там инвоки писать не нужно) .. Дело в том что он умеет генерировать событие в очередь формы. Тоесть он работает как PostMessage по сути. А вот как кроме этих способов я не знаю как добавить в очередь формы пользовательские события. Я про это и спрашивал. Просто если не добавлять прям в очередь событий формы своё событие, то вроде как ни крути а исполняться код будет не в потоке формы а гдето-то у нас в коде. А это как я уже несколько раз повторял не хорошо.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
11.10.2015, 19:31
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Как я уже говорил, по хорошему надо чтобы программа была в одном потоке, а форма в другом и что бы они были по максимуму независимы.
Отделение UI от логики должно состоять в первую очередь в разделении на классы. А между классами должны быть eventы. Если какое-то событие может вызываться в другом потоке, то расставить инвоки, только и всего. Не вижу тут никаких логических противоречий и трудностей.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Дело в том что он умеет генерировать событие в очередь формы.
Я вот сколько читаю, так и не понял, что же это за очередь такая. Знаю очередь оконной процедуры у формы, туда воркер по идее ничего кидать не должен и использует он те же самые eventы. Практическая разница как раз таки в том, что не надо писать инвоки остальное все тонкости реализации.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Invoke не смертельно конечно. Кроме одного НО. Он возникает только в том случе, когда мы пытаемся напрямую достучаться до контролов из другого потока. А это явный признак того что UI и основной код программы не полностью разделены. Вот когда мы используем делегаты, то мы код, который должен быть по идее в потоке UI, начинаем исполнять в потоке основного кода программы, вот тогда и возникает необходимость инвоков. Тоесть инвоки это не проблемма. Проблемма это наличие причины по которой эти инвоки надо использовать.
Не вижу тут никакой проблемы. ООП-то для чего придумано? Все разделение успешно реализуется с его помощью.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
И тут явно путаница возникает, так как event к реальным событиям отношения не имеет.
Ну в терминологии .NET эти события вполне "реальны" Если этим словом в другом месте называют что-то другое, то это совершенно не означает, что тут есть какой-то "обман".
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
А что касается Task то принципиального различия нет - это тоже просто другой поток. Разница лишь в том как оно создается, поддерживается и убивается. BGworker тоже например пул а не просто поток.
Да, тут все верно. Правда, если использовать не Task.Run, а async/await, то там все несколько сложнее.
Кстати говоря, отличный пример с использованием воркера в тему уже давно выложил insite2012, почему вы не взяли на вооружение его?

Добавлено через 12 минут
В целом проблема, на мой взгляд, заключается в том, что вы мыслите понятиями из низкоуровневого программирования, а не ООПшными. Что для данного языка совершенно не подходит.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
12.10.2015, 06:37  [ТС]
Отделение UI от логики должно состоять в первую очередь в разделении на классы. А между классами должны быть eventы. Если какое-то событие может вызываться в другом потоке, то расставить инвоки, только и всего. Не вижу тут никаких логических противоречий и трудностей.
Если считать что отделение UI от логики должно быть только в классах, то действительно использовние eventов ни чему не противоречит. Другое дело что загружать поток логики вопросами UI далеко не всегда разумно. Взять хотябы пример если логика на серевере где-то делается. Заставлять тогда сервер обрабатывать код клиенткого UI уже не так логично. Или даже на одном компе, если UI довольно громоздкое, (что вполне себе может быть) а его обработка весьма трудоёмкая, то есть 2 варианта: тормозит всё и логика и UI(так как всё всемете обрабатывается); тормозит только UI а логика обрабатывается сама по себе, и принимает от UI только то, что UI успело насчитать(далеко не все события UI есть смысл обрабатывать, например при перемещении курсора нет надобности каждую "миг" обрабатывать изменение курсора мышки). Ну и ещё один, как мне кажется, очень важный пример, это возможность использовать UI и основную программу в разных процессах - тогда основной код и UI могут писать абсолюбтно разные люди на разных языках (согласитесь что форму на шарпе написать удобнее чем на голых C, а основную программу, иногда разумнее НЕ писать на шарпе). Плюс если процессы UI и основной логики разные, но есть некоторый оговоренный способ взаимодействия, то можно написать ещё и ешё различные реализации модулей UI и использовать тот или иной модуль как вам захочется. Вот это и есть максимальная независимость UI и основого кода программы.

Я вот сколько читаю, так и не понял, что же это за очередь такая. Знаю очередь оконной процедуры у формы, туда воркер по идее ничего кидать не должен и использует он те же самые eventы. Практическая разница как раз таки в том, что не надо писать инвоки остальное все тонкости реализации.
Есть два потока. В одном из них что-то выполняется, но тут вдруг нам приспичило чтобы в этом потоке срочно исполнилось что-то ещё, причем Когда и Что становится ясно только во время испольнения второго потока, но он ооочень занят и надо чтобы это сделал первый поток. Из самых общий соображений можно устроить принудительное прерывание (interupt) первому потоку с push-pop'ами, но это очень суровый метод. Есть другой вариант - первый поток регулярно в вечном лупе или по таймеру опрашивает второй поток на вопрос "есть чё мне для тебя сделать?". И есть ещё один вариант, когда первый поток сделав работу спит и никого не о чём не спрашивает, но у него есть возможность проснуться от сообщения что пора работать, притом, если первый и так работал, а ему ещё от второго пришло задание, и ещё потом, то он должен не проигнорировать, а записать в Очередь то, что ему надовали делать. Вот чтобы второй поток мог дать работу первому, надо чтобы либо первый сам опрашивал, либо имел возможность пробудиться. А это возможно только если у первого реализован способ добавления задач в очередь (журнал работ с карандашиком в который ему записывают что нужно будет сделать когда будет свободное время) либо если он опрашивает сам остальных. Опрос остальных не очень удобен - работодателей может быть много.. да и не всегда они работу дают, и тратить время на опрос особо нет хочется. (В принципе МОЖНО КОЕНЧНО опрашивать это вполне допустимо, более того иногда это единственный возможный вариант) В итоге было бы хорошо чтобы у первого потока был журнал заданий.. и Очередь ) Вот в Форме как раз и есть нечто подобное. Пришло событие от клавы или мышки - форма обработкала. Ну в самом деле, не драйвер же клавы этим занимается ) Всё же обработка клика мышки это работа потока формы... Зуб не дам, но я разочаруюсь совсему уже в Винде если узнаю что это не так.

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

Кстати говоря, отличный пример с использованием воркера в тему уже давно выложил insite2012, почему вы не взяли на вооружение его?
Вот тут вот я должен ещё раз сказать всем ВАМ спасибо и insite2012 и EvilFromHell и wm_leviathan, за ваши советы. Собственно именно прочитав их я понял куда нужно смотреть в мсдн и про что читать, и по сути именно из всех ваших примеров я и получил свой вариант.

А что касается ООП и низкоуровневого программирования, то, в силу того что в ООП я действительно плохо рабираюсь, то сравнивать их я не могу. Но на мой взгляд общая логика построения устройства или программы не должна зависеть от языка программирования. Но вот реализация то конечно зависит, и не всем языкам та или иная логика (архитектура, общий смысл) доступна для реализцаии.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
12.10.2015, 07:49
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Вот это и есть максимальная независимость UI и основого кода программы.
Еще раз повторю-шарп-это ООП язык. А вы пытаетесь навязать этому языку чуждую ему концепцию Это все было бы абсолютно верно, если бы речь шла про язык, который не поддерживает ООП, но не тут. Суть в том, что, согласно принципам инкапсуляции, в классе, который отвечает за UI, ничего кроме UI и не должно выполняться. Вся логика должна обрабатываться в другом классе, ссылка на объект которого кидается в UI, в UI же надо просто подписаться на эвенты и дергать методы того объекта. Если эвенты поступают из другого потока-ничто не мешает расставить инвоки. А вот в классе, который отвечает за логику, как раз таки для длительных операций надо запускать потоки, а сложить 2 числа можно и в том же потоке, где UI-больше расходов будет на создание потока, чем на само действие. Именно по этой логике написаны оба варианта, какие я и insite2012 предлагали в теме.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Есть два потока. В одном из них что-то выполняется, но тут вдруг нам приспичило чтобы в этом потоке срочно исполнилось что-то ещё, причем Когда и Что становится ясно только во время испольнения второго потока, но он ооочень занят и надо чтобы это сделал первый поток. Из самых общий соображений можно устроить принудительное прерывание (interupt) первому потоку с push-pop'ами, но это очень суровый метод. Есть другой вариант - первый поток регулярно в вечном лупе или по таймеру опрашивает второй поток на вопрос "есть чё мне для тебя сделать?". И есть ещё один вариант, когда первый поток сделав работу спит и никого не о чём не спрашивает, но у него есть возможность проснуться от сообщения что пора работать, притом, если первый и так работал, а ему ещё от второго пришло задание, и ещё потом, то он должен не проигнорировать, а записать в Очередь то, что ему надовали делать. Вот чтобы второй поток мог дать работу первому, надо чтобы либо первый сам опрашивал, либо имел возможность пробудиться. А это возможно только если у первого реализован способ добавления задач в очередь (журнал работ с карандашиком в который ему записывают что нужно будет сделать когда будет свободное время) либо если он опрашивает сам остальных. Опрос остальных не очень удобен - работодателей может быть много.. да и не всегда они работу дают, и тратить время на опрос особо нет хочется. (В принципе МОЖНО КОЕНЧНО опрашивать это вполне допустимо, более того иногда это единственный возможный вариант) В итоге было бы хорошо чтобы у первого потока был журнал заданий.. и Очередь ) Вот в Форме как раз и есть нечто подобное. Пришло событие от клавы или мышки - форма обработкала. Ну в самом деле, не драйвер же клавы этим занимается ) Всё же обработка клика мышки это работа потока формы... Зуб не дам, но я разочаруюсь совсему уже в Винде если узнаю что это не так.
Опять же, логика понятная, но низкоуровневая и ни разу не ООПшная Тут, в большинстве случаев, заморачиваться подобными вещами просто не нужно, такого рода вопросы обычно может порешать компилятор, а вам достаточно написать BeginInvoke, который, собственно, и делает именно то, что вы хотите, если судить по этому описанию. Про оконную процедуру-верно, она выполняется в потоке формы.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
по сути именно из всех ваших примеров я и получил свой вариант
В варианте от insite2012 было удобно сделано через наследование от вокрера. В моем варианте было сделано через классический поток и события. Вы же повырезали все из этих вариантов, что связано с ООП, и добавили лишний поток, что привело к избыточности и к тому, что логика и UI у вас не разделены, хотя вроде как именно этого вы хотите добиться
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
12.10.2015, 11:40  [ТС]
Еще раз повторю-шарп-это ООП язык. А вы пытаетесь навязать этому языку чуждую ему концепцию
Концепция которую предлагаю я не чуждая никому ). Разделение на потоки и межпоточное взаимодействие на уровне WaitHandle полностью вписывается в C# и его мсдн. Более того. Межпроцессовое взаимодействие тоже предусмотрено в C# и в мсдн соответсвенно через WaitHandle. https://msdn.microsoft.com/en-... 10%29.aspx Named event wait handles can also be used to synchronize activities across application domains and processes, whereas monitors are local to an application domain.
Разделение UI и основного кода это не только разделение классов. Запуск паралельных процессов и их отключение по мере надобности вполне себе распространненная потребность. И это совсем не низкоуровневое программирование. И примеры задач и методы их реализации, которые я приводил, нельзя назвать низкоуровневыми. Мы не пишем драйвера, не идём в обход планровщика задач, не пишем код на асме вместо компилятора шарпа. Наоборот, я говорю на уровне уже готовых программ, езешников, возможно, коды которых написаны на разных языках и нет исходников ни возможности их изменить.НО! Но есть описание именных WaitHandle'ов с которыми эти программы могут работать. Я уже приводил пример, про музыкальный плеер. Часть кода для него лучше писать на С++. А другую часть на C#. И это удобнее будет и надежнее и рациональнее, чем всё писать на одном языке.
Пусть C# ООП язык. Но слишком много существует задач, которые на нём просто неудобно делать, и не меньше тех задач, для которых он идеален. А есть задачи которые совмещают в себе 2 класса подзадач, котоыре на шарпе удобно и котоыре не удобно делать. Вот тогда вполне разумно разбивать весь проект на подпроекты-модули, и подключать их время от времени в процессе работы. И event'ы тут скорее будут обузой нежели чем удачным решением проблемм. А вот WaitHandl'ы вполне себе подойдут.
Проблема только в том, что WinForms не имеет явной возможности реагировать на внешние WaitHandl'ы. (Точнее я так её и не нашёл). Создавать ещё один поток можно, да, согласен. Можно из этого потока через инвоки деркать контролы, да тоже согласен. Но что если вывод данных в форму из этого потока не самый тривиальный, типа как лабела текст поменять, а что-то более серьёзное, продолжительное, динамичное... Но при всём при этом, от основного потока по хорошему требуется только сказать форме ПроснисьИРаботай_(задание_35) и продолжить заниматься своими вещами. В случае event'ов вся эта муторная, продолжительная но не слишком КРИТИЧНАЯ работа ложится на главный поток. А поток формы балду пинает... Как то это не правильно. Тут нет ничего низко уровневого. Нет попирания законов ООП. Просто логичное и рациональное распеределение обязанностей и ресурсов ОС или железа. Поток можно рассматривать как нечто большее чем виртуально созданное перепрыгивание ОС с одной задачи на другую. Поток может быть и на разных ядра, процессроах, на разных устройствах и вобще между нашим компом и серверами альфацентавры , которые реализуют между собой оговоренный протокол взаимодействия. Ну не добиться этих межгалактических взаимодействий c незнакомыми программами через event'ы. А если и добиться.. то прейдётся платить альфацентавре за использование их вычислительных мощностей
Так вот WinForms имеют свою очередь, но я не знаю как ещё в неё встать, кроме как через BGWorker и его Progress событие. Он нужен только для этого. В нём можно спать, а можно работать в вечном лупе. Он может принимать внешние WaitHandl'ы и слать их. Он может работать с контролами формы в своём потоке через инвоки либо в потоке формы через событие ProgressChanged. Тоже самое с event'ами нельзя уже сделать. Можно правда сделать через PostMessage, но вечный луп в него не засунешь без DoEvents.
Вы же повырезали все из этих вариантов, что связано с ООП, и добавили лишний поток, что привело к избыточности и к тому, что логика и UI у вас не разделены, хотя вроде как именно этого вы хотите добиться
Вот тут я не понимаю, почему у меня не разделена логика и UI? Может из примера было не очеь ясно, но логика программы не в воркере а в MyMainF. А он в отдельном потоке. Классы я не стал разные делать - не в них суть. Но сделать то их не проблемма. Или только в этом заключается замечание о "неразделении"...?
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
12.10.2015, 16:59
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Разделение UI и основного кода это не только разделение классов.
В первую очередь - именно их.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
по хорошему требуется только сказать форме ПроснисьИРаботай_(задание_35) и продолжить заниматься своими вещами
Ну и чем по-вашему тут не подходит BeginInvoke? Он сразу возвращает управление потоку, в котором вызван, а форма уже сама разбирается, когда ей выполнять указанный код.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Классы я не стал разные делать - не в них суть. Но сделать то их не проблемма.
Эмм, а в чем вообще тогда смысл разделения UI и интерфейса? С точки зрения ООП смысл в том, чтобы каждый класс инкапсулировал в себе какой-то функционал, а остальное вокруг него с легкостью можно было заменить. Вот к примеру проектик, который я недавно писал на фрилансе. Надо было сделать бота для нескольких букмекерских контор. Не буду же я для каждого сайта писать свой UI, хотя работа с сайтами технически совершенно разная. Поэтому у меня там есть абстрактный класс, в котором объявлены сигнатуры методов, свойств и эвентов, которые интересуют UI. Дальше для каждого сайта наследуюсь от этого класса и реализую это все. UI же у меня в виде UserControlа, и принимает в конструктор объект, соответствующий абстрактному классу. Опрос сайтов происходит, естественно, в отдельном потоке, а все обработчики эвентов в UI сделаны через инвоки. В результате, если я захочу добавить новый сайт, мне вообще не надо трогать UI-достаточно унаследоваться от того абстрактного класса и переопределить нужные методы. В данной программе, понятное дело, ничего нигде не виснет. И как бы я то же самое реализовал без ООП?
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
13.10.2015, 16:19  [ТС]
Спасибо большое за ваши ответы и замечания. Очень полезны оказались для меня.
Ну и чем по-вашему тут не подходит BeginInvoke?
Вобще говоря подходит, это прямой аналог PostMessage. С той лишь разницей что просто PostMessage шлёт тока "сигнал" о том что нужно делать и параметры какие-то, а BeginInvoke шлёт ещё и код, код который будет исполнятся в порядке очереди в потоке формы, а тот поток что отправил этот код продолжит своё выполнение. Если честно я это понял только после вашего вопроса "чем тут не подходит...", когда задумался.. "а правда, и чем же?!..". Покопался поподробнее, почитал и вобщем оказалось, что это действительно то о чём я спрашивал - прямой аналог PostMessage.
Далее дело вкуса - можно писать код прям в делегат инвока в том потоке и классе из которого будет вызываться BeginInvoke, а можно (что мне ближе) в делегате указать только выполнение функции из класса формы, где её код полностью и будет.
Единственный момент, который не ясен с BeginInvoke, так это то, можно ли с помощью них работать не с двумя разными потоками одного приложения, а с двумя разными процессами двух разных приложений? Скажем запустить уже готовый екзешник программки, в которой только форма с её функционалом, и попытаться залезть в очередь этой формы из другого процесса. По идее это мягко говоря не безопасно и такие возможности должны быть зарезаны на корню... Казалось бы через WaitHandl'ы 'этой проблемы не было бы (код правда тогда тоже вроде не отправить... хотя кто знает... надо покопать).

Про разделение классов и ООП...
Конечно это важно, но это больше филосовский вопрос. На асме всё равно классов нет, а всё к нему сводится)
Главное как я уже говорил и как вы подтвердили это своим примером про ваш проект букмекеров - Существуют задачи для готорых C# и ООП в целом просто идеальны. И раз это можно на них сделать, более того если это на них уже сделано, и работает без проблемм, то зачем выдумывать альтернативу, если в ней нет необходимости. В мире и так полно задач котоыре уже поставлены, и которые очень нужно решить.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
13.10.2015, 18:12
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
это прямой аналог PostMessage
Скорее даже не аналог, а обертка, которая позволяет не заморачиваться вещами типа запихивания нужных байтов в нужное место в lparam.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Единственный момент, который не ясен с BeginInvoke, так это то, можно ли с помощью них работать не с двумя разными потоками одного приложения, а с двумя разными процессами двух разных приложений?
Не, просто так влезть в чужое приложение и что-то там выполнить не выйдет
Again, the delegate information is not passed to the message queue. Internally there is a "stack" of callback objects where the delegate information is stored. The method called by the wndproc routine only needs to pop the topmost callback from the list to get the delegate information. It can then invoke it. I recommend that if you are still confused about how this happens you should open the source code in Reflector and review it. Look for Control.BeginInvoke and you'll see all the code. As for the conversion you will see that BeginInvoke calls PostMessage after it pushes the callback data onto the internal list.
То есть там по факту есть некий список с делегатами, о котором знает оконная процедура, куда BeginInvoke добавляет свой делегат, а потом вызывает PostMessage, который оконная процедура понимает как сигнал о том, что такой-то делегат из списка надо выполнить. При желании-есть .NetReflector, можно распотрошить системные DLLки и глянуть, что там и как реализовано.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Казалось бы через WaitHandl'ы 'этой проблемы не было бы (код правда тогда тоже вроде не отправить... хотя кто знает... надо покопать)
Такое в ряд ли возможно хоть где-то без лютых низкоуровневых извращений с залезанием в память другого процесса Другое дело, если второе приложение свое, то можно посылать ему что-то через сокеты/пайпы/еще что-нибудь, а потом уже пытаться выполнять. Но это все надо достаточно редко.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Конечно это важно, но это больше филосовский вопрос. На асме всё равно классов нет, а всё к нему сводится)
Ну можно и в двоичном коде писать программы, только дешевизной, понятностью, легкостью поддержки и скоростью разработки они явно отличаться не будут
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Существуют задачи для готорых C# и ООП в целом просто идеальны
ООП и язык C#-достаточно универсальные инструменты, я с трудом представляю задачу достаточно большого объема, для которой бы ООП не подошло. Другой вопрос в том, что с ООП связаны некоторые накладные расходы в плане производительности,а язык C# завязан на .NET, это, собственно, и ограничивает их область применения. Ну и что-то низкоуровневое на нем писать тяжело, почти все навороты языка нельзя будет использовать.

Добавлено через 6 минут
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Далее дело вкуса - можно писать код прям в делегат инвока в том потоке и классе из которого будет вызываться BeginInvoke, а можно (что мне ближе) в делегате указать только выполнение функции из класса формы, где её код полностью и будет.
Ну так-этот вопрос уже решается при помощи eventoв. Подписываетесь на эвенты, а в обработчике оборачиваете код в Invoke:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
       
SD.SomethingWrong += OnSomethingWrong;
 private void OnSomethingWrong(Exception e)
        {
            this.BeginInvoke(new Action(() => {
                ErrorLabel.Text = e.Message;
                if (e.Message == "Нет связи с сервером") {
                    Timer t = new Timer();
                    t.Tick += (s,ee) => { ErrorLabel.Text = ""; (s as Timer).Stop(); (s as Timer).Dispose(); };
                    t.Interval = 20000;
                    t.Start();
                    return; }
                button1.PerformClick();
            })); 
        }
В данном коде-обработчик эвента, вызываемого в другом потоке.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
13.10.2015, 19:39  [ТС]
ООП и язык C#-достаточно универсальные инструменты, я с трудом представляю задачу достаточно большого объема, для которой бы ООП не подошло.
Вот не то что-бы ООП не подошло, но C# в текущем варианте (родные библиотеки, без сторонних самоделок) очень плохо умеет работать с устройствами, тем более на низком уровне (я не про драйвера). А задачи такие: несколько (порядка 10ка) различных устройств USB, video, com, audio устройства собирают данные от некоторого процесса а так же управляют чем-то (моторами какимто или внешними генераторами напряжения), ацп и проче проче прочее. И всё полученные данные должны отправляться на комп, там обрабатываться довольно ресурсоёмкими алгоритмами, отображаться в виде графиков, и прочих логов на компе, плюс необходимо всем этим набором устройств управлять с компа, не с конфиг файлов или консоли а с помощью виндовых форм. Винда нужна тупо из-за того что слишком много софта под неё сделано + пользователи её не боятся. Короче надо ВИНДУ (. Вот всё эту свору меню писать даже на С++ довольно трудоёмко и не очень удобно, по сравнению с C#. А вот часть которая отвечает за работу с железом уже неудобно писать на C#. Вот собственно и пример.
Выхода два: забить на удобство и всё делать на С++, или же часть на C# а часть на С++. Ну с первым вариантом я уже намучался в своё время... вот собственно и думаю как бы так сделать, чтобы мой пример с ком-портом после разрастания не превратилась в адского монстра...Я его делал только чтобы отдельный модуль протестить когда спаял. Ща пытаюсь придумать что-то вроде универсального интерфейса между отдельными кусками программы, который бы для всех языков был бы доступен. В этом ключе почемуто хочется чтобы програмные модули (назову так разные подпрограммы для разных устройст, котоыре будут запускаться независимо и взаимодействовать между собой через ... вот тут я тоже ещё не выбрал через что.) работали с одним каким-то общим "интерфесом". Всмысле способ обмена данными и событиями друг с другом был у всех одинаков,... и у окон тоже. А если инвоки не могут между разными процессами работать, то наверно они тут не подойдут. Конечно можно каждому устройству свою пару делать программа-окно.... Но пока не определился.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.10.2015, 19:39

Как правильно использовать события и свойства элемента CheckBox
Как получить обратное действие? Например у меня на форме: checkBox1 textBox1 Мне нужно чтобы когда была галочка (Что введенно...

SerialPort: Ожидание События или получение ответа из потока чтения флуда байтов
Имеется: OpenPort() - открывает порт и любимый Поток readport() - Поток который считывает всё, всегда и везде lan() - метод который...

Ожидание события
Есть некоторая модель данных, в которой постоянно что-то происходит. Изменяются данные, срабатывают её события и прочее. Нужен совет по...

Qt ожидание события
Виджет получил событие. Действие надо сделать после прошествии какого то времени, если не получено следующее событие до того как пройдет...

ожидание события
Есть несколько потоков и глобальная переменная. Можно ли сделать так что бы каждый поток ожидал пока переменная не приняла какое ли бо...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru