powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / потоки в C#
76 сообщений из 76, показаны все 4 страниц
потоки в C#
    #38674887
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
дело такое - опрашиваю ком порты. есть функция и класс, отвечающие за разные методы.
приходится ставить thread.sleep() чтобы получить значение с ком порта, потому что сразу они не приходят.
так вот - все это дело крутится в таймере.
пытаюсь выключить таймер - он мне ругается.
как остановить thread.sleep по клику?
...
Рейтинг: 0 / 0
потоки в C#
    #38674892
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerдело такое - опрашиваю ком порты. есть функция и класс, отвечающие за разные методы.
приходится ставить thread.sleep() чтобы получить значение с ком порта, потому что сразу они не приходят.
так вот - все это дело крутится в таймере.
пытаюсь выключить таймер - он мне ругается.
как остановить thread.sleep по клику?Зачем таймер? У компорта есть события.
...
Рейтинг: 0 / 0
потоки в C#
    #38674894
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и ? мне нужно поинтервально опрашивать его
...
Рейтинг: 0 / 0
потоки в C#
    #38674895
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может можно узнать состояние потока и запустить его не ожидая слип
...
Рейтинг: 0 / 0
потоки в C#
    #38674903
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerи ? мне нужно поинтервально опрашивать егоОбычно поинтервально делают запрос+ответ.

А если девайс постоянно шлёт данные в порт, без запроса, то лучше принимать данные по событию.

авторприходится ставить thread.sleep() чтобы получить значение с ком порта, потому что сразу они не приходят.Этот момент проясни, обычно это решается через read timeout в порте.
...
Рейтинг: 0 / 0
потоки в C#
    #38674905
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
readtimeout не помогает. пробовал
_COM.ReadTimeout = timeout;
_COM.WriteTimeout = timeout;
да идет запрос-ответ. в общем, если не привязываться к технологии возможно прибить слип? хотя, может я таймаут неправильно выставил? но вот сколько не менял - разницы ровным счетом никакой
...
Рейтинг: 0 / 0
потоки в C#
    #38674911
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roer,

Тайм аут нужно задавать перед открытием порта. В милисекундах
...
Рейтинг: 0 / 0
потоки в C#
    #38674914
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот усечченный вариант, скелет ак сказать, но суть ясна


Код: 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.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
namespace ServiceUniOPc
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
           
        }


        #region tcpconnect
        private void SelectTcp()  //com port
        {
           this.timer1.Start();           
        }


        private void timer1_Elapsed(object sender, EventArgs e)
        {
		for (int i = 0; i < ds.Tables[0].Rows.Count; i++)               
                        Connect(dt.Rows[i][1].ToString(), dt.Rows[i][2].ToString() + "\r", Convert.ToInt32(dt.Rows[i][3]), i);
           
        }

        void Connect(String server, String message, Int32 port, Int32 id)
        {
            try
            {
                // Create a TcpClient.
                // Note, for this client to work you need to have a TcpServer 
                // connected to the same address as specified by the server, port
                // combination.
                TcpClient client = new TcpClient(server, port);

                // Translate the passed message into ASCII and store it as a Byte array.
                Byte[] data = Encoding.UTF8.GetBytes(message);
                // Get a client stream for reading and writing.
                

                NetworkStream stream = client.GetStream();

                // Send the message to the connected TcpServer. 
                stream.Write(data, 0, data.Length);

            

                // Receive the TcpServer.response.

                // Buffer to store the response bytes.
                data = new Byte[256];

                Thread.Sleep(300);
                

                // String to store the response ASCII representation.              

                // Read the first batch of the TcpServer response bytes.
                Int32 bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
  
                // Close everything.
                stream.Close();
                client.Close();

            }
			
        }        
        #endregion 


        #region comport
        private void SelectCom()  //com port
        {
                        InitAll();        
        }
      


        private void InitAll()
        {
               allListeners = new List<OneCOMSpectator>();

                for (int xx = 0; xx < ds3.Tables[0].Rows.Count; ++xx)
                {
                    string com = "COM" + dt3.Rows[xx][1];
                    string send = dt3.Rows[xx][3].ToString() + "\r";
                    string idcom = dt3.Rows[xx][0].ToString();
                    int BaudRate = Convert.ToInt32(dt3.Rows[xx][2]);
                    string parity = dt3.Rows[xx][10].ToString();
                    int databit = Convert.ToInt32(dt3.Rows[xx][11]);
                    double stopbit = Convert.ToDouble(dt3.Rows[xx][12]);
                    string flowcontrol = dt3.Rows[xx][13].ToString();
                    int timeout = Convert.ToInt32(dt3.Rows[xx][14]);
                    string parseFunc = dt3.Rows[xx][4].ToString();
                    allListeners.Add(new OneCOMSpectator(com, BaudRate, send, idcom, parity, databit, stopbit, flowcontrol, timeout, parseFunc));
                }
                min = Convert.ToInt32(dt3.Rows[0][14]);
                for (int i = 0; i < ds3.Tables[0].Rows.Count; i++)
                {
                    if (Convert.ToInt32(dt3.Rows[i][14]) < min)
                        min = Convert.ToInt32(dt3.Rows[i][14]);
                }
               
                    this.timer3 = new System.Timers.Timer();
                    this.timer3.Enabled = true;
                    this.timer3.Interval = min;
                    this.timer3.Elapsed += new System.Timers.ElapsedEventHandler(this.timer3_Elapsed);
                    this.timer3.AutoReset = true;
                    this.timer3.Start();
         
          
        }

        private void timer3_Elapsed(object sender, EventArgs e)
        {
                foreach (OneCOMSpectator comListener in allListeners)
                {
                    comListener.TransferData();
                }

        }

        class OneCOMSpectator
        {
             
            SerialPort _COM;
            string DataToSend;
            string IdCom;
            string ParseGlob = "";

            internal OneCOMSpectator(string portNumber, int bodRate, string dataTosend, string idcom, string parity, int databit, double stopbit, string flowcontrol, int timeout, string parse)
            {
                IdCom = idcom;
                DataToSend = dataTosend;
                _COM = new SerialPort(portNumber, bodRate);

                if (parity.ToLower() == "none")
                    _COM.Parity = System.IO.Ports.Parity.None;
                else if (parity.ToLower() == "even")
                    _COM.Parity = System.IO.Ports.Parity.Even;
                else if (parity.ToLower() == "mark")
                    _COM.Parity = System.IO.Ports.Parity.Mark;
                else if (parity.ToLower() == "odd")
                    _COM.Parity = System.IO.Ports.Parity.Odd;
                else if (parity.ToLower() == "space")
                    _COM.Parity = System.IO.Ports.Parity.Space;

                _COM.DataBits = databit;

                if (stopbit == 0)
                    _COM.StopBits = StopBits.None;
                else if (stopbit == 1)
                    _COM.StopBits = StopBits.One;
                else if (stopbit == 1.5)
                    _COM.StopBits = StopBits.OnePointFive;
                else if (stopbit == 2)
                    _COM.StopBits = StopBits.Two;

                if (flowcontrol.ToLower() == "none")
                    _COM.Handshake = Handshake.None;
                else if (flowcontrol.ToLower() == "rts/cts" || flowcontrol.ToLower() == "rts\\cts")
                    _COM.Handshake = Handshake.RequestToSend;
                else if (flowcontrol.ToLower() == "xon/xof" || flowcontrol.ToLower() == "xon\\xof")
                    _COM.Handshake = Handshake.RequestToSendXOnXOff;
                else if (flowcontrol.ToLower() == "dtr/dsr" || flowcontrol.ToLower() == "dtr\\dsr")
                    _COM.Handshake = Handshake.XOnXOff;

                _COM.ReadTimeout = timeout;
                _COM.WriteTimeout = timeout;
                if (parse != "")
                    ParseGlob = parse;


                _COM.DataReceived += new SerialDataReceivedEventHandler(_COM_DataReceived);

            }

            void _COM_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                    Thread.Sleep(100);
                    // Пришли данные
                    String indata = _COM.ReadExisting();
                    indata = indata.Substring(0, indata.Length - 1);
                    String Mystr = "";
                    // Чето с ними делаем  

            }


            internal void TransferData()
            {
                try
                {
                    if (_COM.IsOpen)
                    {
                        // Если порт открыт, значит какой-то косяк, девайс не ответил, здесь обрабатываем

                        // Закрываем
                        _COM.Close();
                    }

                    // Открываем
                    _COM.Open();
                    _COM.Write(DataToSend);
                }
                catch 
                {
                    
                    return;
                }
            }
        }    
        #endregion

        #region start
        protected override void OnStart(string[] args)
        {

                      SelectTcp(); 
              
                    SelectCom();
             
                
           
        }
        #endregion

        #region stop
        protected override void OnStop()
        {
                if (this.timer1.Enabled) this.timer1.Stop();
               
                if (this.timer3.Enabled)  this.timer3.Stop();
            
        }
        #endregion

    }
}




...
Рейтинг: 0 / 0
потоки в C#
    #38674916
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
так и делаю
Код: 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.
           IdCom = idcom;
                DataToSend = dataTosend;
                _COM = new SerialPort(portNumber, bodRate);

                if (parity.ToLower() == "none")
                    _COM.Parity = System.IO.Ports.Parity.None;
                else if (parity.ToLower() == "even")
                    _COM.Parity = System.IO.Ports.Parity.Even;
                else if (parity.ToLower() == "mark")
                    _COM.Parity = System.IO.Ports.Parity.Mark;
                else if (parity.ToLower() == "odd")
                    _COM.Parity = System.IO.Ports.Parity.Odd;
                else if (parity.ToLower() == "space")
                    _COM.Parity = System.IO.Ports.Parity.Space;

                _COM.DataBits = databit;

                if (stopbit == 0)
                    _COM.StopBits = StopBits.None;
                else if (stopbit == 1)
                    _COM.StopBits = StopBits.One;
                else if (stopbit == 1.5)
                    _COM.StopBits = StopBits.OnePointFive;
                else if (stopbit == 2)
                    _COM.StopBits = StopBits.Two;

                if (flowcontrol.ToLower() == "none")
                    _COM.Handshake = Handshake.None;
                else if (flowcontrol.ToLower() == "rts/cts" || flowcontrol.ToLower() == "rts\\cts")
                    _COM.Handshake = Handshake.RequestToSend;
                else if (flowcontrol.ToLower() == "xon/xof" || flowcontrol.ToLower() == "xon\\xof")
                    _COM.Handshake = Handshake.RequestToSendXOnXOff;
                else if (flowcontrol.ToLower() == "dtr/dsr" || flowcontrol.ToLower() == "dtr\\dsr")
                    _COM.Handshake = Handshake.XOnXOff;

                _COM.ReadTimeout = timeout;
                _COM.WriteTimeout = timeout;
                if (parse != "")
                    ParseGlob = parse;


                _COM.DataReceived += new SerialDataReceivedEventHandler(_COM_DataReceived);
//////////
    if (_COM.IsOpen)
                    {
                        // Если порт открыт, значит какой-то косяк, девайс не ответил, здесь обрабатываем

                        // Закрываем
                        _COM.Close();
                    }

                    // Открываем
                    _COM.Open();
                    _COM.Write(DataToSend);
                }
...
Рейтинг: 0 / 0
потоки в C#
    #38674946
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не вижу, где у тебя чтение порта (не по событию). Назначение тайм аута - выбить эксепшн, если ты обратился к методу read, а он в течении времени не выдал данные
...
Рейтинг: 0 / 0
потоки в C#
    #38674950
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Read existing под это дело не пдходит тк нечего читать - и тайм аут не срабатывает
...
Рейтинг: 0 / 0
потоки в C#
    #38674956
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а что подходит?
...
Рейтинг: 0 / 0
потоки в C#
    #38674960
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
потоки в C#
    #38674991
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
нет. также дергает первые несколько символов.
попробовал
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
      byte[] buf1 = new byte[16];
                

                    // Пришли данные                 
                   _COM.Read(buf1,0,16);
                 
                    // Чето с ними делаем  
                    string tmp = System.Text.Encoding.ASCII.GetString(buf1);
                    MessageBox.Show(tmp);
...
Рейтинг: 0 / 0
потоки в C#
    #38674992
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может есть способ проверить есть ли еще данные которые нужно принять
...
Рейтинг: 0 / 0
потоки в C#
    #38675025
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А ты не знаешь, сколько данных должно прийти в ответ на запрос?
...
Рейтинг: 0 / 0
потоки в C#
    #38675029
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
знаю
...
Рейтинг: 0 / 0
потоки в C#
    #38675033
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerнет. также дергает первые несколько символов.
попробовал
Код: c#
1.
2.
      byte[] buf1 = new byte[16];            
                   _COM.Read(buf1,0,16);



ну так ты тут считываешь 16 байт. Если придет меньше - вывалится exeption после таймаута. Если больше - нужно считывать дальше
...
Рейтинг: 0 / 0
потоки в C#
    #38675035
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как?
...
Рейтинг: 0 / 0
потоки в C#
    #38675042
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты ж сказал, что знаешь, сколько должно прийти байт. С чего их должно быть больше?

Если все-таки не знаешь, то лучше подход с событием применять.
...
Рейтинг: 0 / 0
потоки в C#
    #38675051
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну так че мне цикл делать? как понять то сколько байт пришло?
...
Рейтинг: 0 / 0
потоки в C#
    #38675054
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roer,

попробуй обратиться к свойству _port.BytesToRead, может поможет
...
Рейтинг: 0 / 0
потоки в C#
    #38675096
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чет не вникну
Код: c#
1.
2.
3.
4.
5.
6.
   while (_COM.BytesToRead > 0)
                   {
                       _COM.Read(buf1, 0, 256);
                       string tmp = System.Text.Encoding.ASCII.GetString(buf1);
                       tmp_buf += tmp;
                   }


приходит сначала полчисла и потом полчисла
...
Рейтинг: 0 / 0
потоки в C#
    #38675123
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
по сути, если хранить все что пришло на тике-1 и записывать это на тике , то это и будет число. оно явно должно успеть придти
...
Рейтинг: 0 / 0
потоки в C#
    #38675229
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerну так че мне цикл делать? как понять то сколько байт пришло?Это должно решаться на уровне протокола передачи данных. В протоколах обычно или сначала передаётся размер пакета, или известен символ завершения пакета.
...
Рейтинг: 0 / 0
потоки в C#
    #38675236
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К вы мой код-скелет видели? подскажите как вписать

Код: c#
1.
2.
3.
4.
5.
6.
    while (_COM.BytesToRead > 0)
                   {
                       _COM.Read(buf1, 0, 256);
                       string tmp = System.Text.Encoding.ASCII.GetString(buf1);
                       tmp_buf += tmp;
                   }


приходит полчисла и потом полчисла
...
Рейтинг: 0 / 0
потоки в C#
    #38675269
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerАлексей К вы мой код-скелет видели? подскажите как вписатьТы определись сначала с протоколом, потом будешь вписывать. Один из вариантов примерно такой:
Код: c#
1.
2.
3.
// псевдокод
var length = comPort.ReadIntNumber();
var data = comport.ReadByteArray(length);
...
Рейтинг: 0 / 0
потоки в C#
    #38675295
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerприходит полчисла и потом полчисла

полчисла да полчисла - будет целое число
...
Рейтинг: 0 / 0
потоки в C#
    #38675324
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не понял про протокол
...
Рейтинг: 0 / 0
потоки в C#
    #38675326
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
про полчисла - интересно почему разрыв получается
...
Рейтинг: 0 / 0
потоки в C#
    #38675411
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerпро полчисла - интересно почему разрыв получается
может в Autoexec.bat добавить строку serial_data_number_no_breake = true?
...
Рейтинг: 0 / 0
потоки в C#
    #38675436
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roer, а если серьезно...
устройство может слать вам данные какими угодно частями, не рассматривайте что к вам приходят числа, рассматривайте как поток данных. и SerialPort НИКАК НЕ ДОГАДАЕТСЯ что пришли ваши два числа. полагаю через TCP или UDP вам будет точно такой же поток данных приходить.

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

мне видится что конструкция "while (_COM.BytesToRead > 0)" в вашем случае не самый лучший вариант.

далее, использовать Thread.Sleep - тоже лажа
в классе объявите
EventWaitHandle wh = new AutoResetEvent(false);
... когда поток выполняет проверку нужно ли дальше работать вызывайте
wh.WaitOne() ; - поток уснет
а таймером, раз в 2..10 секунд - wh.Set() - и поток проснется
это же поможет когда нужно поток быстро остановить.
...
Рейтинг: 0 / 0
потоки в C#
    #38675456
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roer, вот упрощенный пример
Код: 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.
    internal class MyComReader
    {
        private SerialPort port;
        private System.Timers.Timer timer;
        private System.Threading.Thread thread;
        readonly EventWaitHandle wh = new AutoResetEvent(false);
        private bool doWork;

        public void ThreadStart()
        {
            doWork = true;
            thread = new Thread(Execute);
            thread.Start();
            timer = new System.Timers.Timer(1000) {Interval = 10000};
            timer.Elapsed += timer_Elapsed;
        }

        public void ThreadStop()
        {
            doWork = false;
            wh.Set();
        }

        void Execute()
        {

            while (doWork)
            {
                if (port == null)
                {
                    port = new SerialPort("COM1", 2400);
                    port.DataReceived += port_DataReceived;
                }
                if(!port.IsOpen)
                    port.Open();

                wh.WaitOne();
            }
            if (port.IsOpen)
                port.Close();
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            wh.Set();
        }

        private string inData;
        void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;

            inData += sp.ReadExisting();

            // проверка, если в InData появилась полная строка - отрезаем кусок
            // и обрабатываем, а лучше в другой поток для обработки передаем
        }
    }
...
Рейтинг: 0 / 0
потоки в C#
    #38675458
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
5.
6.
        public void ThreadStop()
        {
            doWork = false;
            timer.Stop();
            wh.Set();
        }
...
Рейтинг: 0 / 0
потоки в C#
    #38675468
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кифирчик
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
        private string inData;

        void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;

            inData += sp.ReadExisting();

            // проверка, если в InData появилась полная строка - отрезаем кусок
            // и обрабатываем, а лучше в другой поток для обработки передаем
        }
    }

Плохо.
...
Рейтинг: 0 / 0
потоки в C#
    #38675476
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КПлохо.
аргументы?
у меня вот так уже больше года считывает данные с оборудования, пожаловаться не могу.
...
Рейтинг: 0 / 0
потоки в C#
    #38675477
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerне понял про протоколЕщё раз, данные передаются блоками. Есть два основных способа получения блока:

1. Сначала прочитать из порта размер блока данных. Для этого надо прочитать, например, 4 байта и преобразовать их в Int32. Потом, зная размер блока, прочитать известное количество байт.

или

2. Читать из порта побайтно пока не встретится символ завершения блока.
...
Рейтинг: 0 / 0
потоки в C#
    #38675492
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КифирчикАлексей КПлохо.
аргументы?Есть решение проще.
Кифирчику меня вот так уже больше года считывает данные с оборудования, пожаловаться не могу.Это ничего не меняет.
...
Рейтинг: 0 / 0
потоки в C#
    #38675514
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во я как-то давно писал для считывателя электронных карт, может натолкнёт на какие-нибудь мысли.
Код: 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.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
    public class CardReaderDevice : IDisposable
    {
        private static readonly byte[] _password = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

        private SerialPort _port = new SerialPort();
        private ByteCounter _frameIDGenerator = new ByteCounter();

        private CardReaderByteStaffing _byteStaffing = new CardReaderByteStaffing(
            FRAME_STAFFED_BYTE, 
            STAFFED_FRAME_STAFFED_BYTE
        );

        public CardReaderDevice()
        {
            _byteStaffing.AddToMap(FRAME_START, STAFFED_FRAME_START);
            _byteStaffing.AddToMap(FRAME_STOP, STAFFED_FRAME_STOP);
            DeviceInfo = null;
            Active = false;
        }

        public virtual void Dispose()
        {
            Close();
            _port.Dispose();
        }

        #region Open / Close

        public bool Active { get; private set; }
        public CardReaderDeviceInfo DeviceInfo { get; private set; }

        private void InitializePort(string portName)
        {
            _port.PortName = portName;
            _port.BaudRate = 9600;
            _port.DataBits = 8;
            _port.StopBits = StopBits.One;
            _port.Parity = Parity.None;
            _port.Handshake = Handshake.None;
            _port.ReadTimeout = 200;
        }

        public void Open(string portName)
        {
            Close();
            InitializePort(portName);
            CardReaderDeviceInfo deviceInfo;
            _port.Open();
            try
            {
                deviceInfo = ReadDeviceInfo();
                SwitchSignals(CardReaderSignals.BeeperDouble | CardReaderSignals.GreenBeeper);
            }
            catch
            {
                _port.Close();
                throw;
            }
            DeviceInfo = deviceInfo;
            Active = true;
        }

        public void Close()
        {
            if (Active == false)
                return;
            try
            {
                _port.Close();
            }
            catch { }
            DeviceInfo = null;
            Active = false;
        }

        public void Open()
        {
            StringBuilder err = new StringBuilder();
            foreach (string portName in SerialPort.GetPortNames())
            {
                try
                {
                    Open(portName);
                    break;
                }
                catch (Exception E)
                {
                    err.AppendLine(portName + ": " + E.Message);
                }
            }
            if (Active == false)
                throw new InvalidOperationException(
                    "Ошибка открытия считывателя электронных карт:" + 
                    Environment.NewLine + 
                    err.ToString()
                );
        }

        #endregion

        #region Read / Write Utils

        private const int BLOCKS_IN_SECTOR = 4;
        internal const int BLOCK_SIZE = 16;
        internal const int FIRST_USED_BLOCK = 4;        

        private static bool IsSystemBlock(int nBlock)
        {
            return
                nBlock == 0 ||
                (nBlock + 1) % BLOCKS_IN_SECTOR == 0;
        }

        internal static void IncrementBlock(ref int currentBlock)
        {
            do
            {
                currentBlock++;
            }
            while (IsSystemBlock(currentBlock));
        }

        #endregion

        #region Commands

        private CardReaderDeviceInfo ReadDeviceInfo()
        {
            byte[] response = ExecuteCommand(0x00, null);
            string deviceName = Encoding.GetEncoding(1251).GetString(response, 3, 20).TrimEnd('\0').Trim();
            return new CardReaderDeviceInfo() { DeviceName = deviceName };
        }

        public void SwitchSignalsStartCommand()
        {
            SwitchSignals(CardReaderSignals.GreenBeeper | CardReaderSignals.BeeperOne);
        }

        public void SwitchSignalsEndCommand()
        {
            SwitchSignals(CardReaderSignals.GreenBeeper | CardReaderSignals.BeeperOne);
        }

        private void SwitchSignals(CardReaderSignals signal)
        {
            byte[] response = ExecuteCommand(0x21, new byte[] { (byte)signal });
            ValidateAck(response);
        }

        public void InitializeCard()
        {
            ResetCard();
            SelectCard();
        }

        private void ResetCard()
        {
            ValidateAck(ExecuteCommand(0x22, null));
        }

        private void SelectCard()
        {
            ExecuteCommand(0x45, new byte[] { 0 });
        }

        public void AuthorizeBlockOnce(byte nBlock)
        {
            if (nBlock % BLOCKS_IN_SECTOR == 0)
                AuthorizeBlock(nBlock);
        }

        public void AuthorizeBlock(byte nBlock)
        {
            if (_password.Length != 6)
                throw new ArgumentException("g_Password.Length != 6");
            byte[] cmdData = new byte[8];
            cmdData[0] = 0x02; // ключ содержится в команде
            cmdData[1] = nBlock;
            _password.CopyTo(cmdData, 2);
            ExecuteCommand(0x50, cmdData);
        }

        public byte[] ReadBlock(byte nBlock)
        {
            if (IsSystemBlock(nBlock))
                throw new InvalidOperationException("Попытка чтения из системного блока сектора. Адрес блока: " + nBlock.ToString());
            byte[] response = ExecuteCommand(0x51, new byte[] { nBlock });
            byte[] result = new byte[BLOCK_SIZE];
            Array.Copy(response, 3, result, 0, BLOCK_SIZE);
            return result;
        }

        public void WriteBlock(byte nBlock, byte[] data)
        {
            if (IsSystemBlock(nBlock))
                throw new InvalidOperationException("Попытка записи в системный блок сектора. Адрес блока: " + nBlock.ToString());
            if (data.Length != BLOCK_SIZE)
                throw new ArgumentException("data.Length != BLOCK_SIZE");
            byte[] cmdData = new byte[BLOCK_SIZE + 1];
            cmdData[0] = nBlock;
            data.CopyTo(cmdData, 1);
            byte[] response = ExecuteCommand(0x52, cmdData);
            ValidateAck(response);
        }

        #endregion

        #region Command Management

        private byte[] ExecuteCommand(byte cmd, byte[] data)
        {
            WriteRequest(cmd, data);
            byte[] response = ReadResponse();
            ValidateFrameID(response);
            ValidateNack(response);
            return response;
        }

        private void ValidateFrameID(byte[] response)
        {
            if (response[1] != _frameIDGenerator.CurrentValue)
                throw new FormatException("response[1] != _FrameID");
        }

        private void ValidateNack(byte[] response)
        {
            if (response[2] == REPLY_ACK_NACK)
            {
                byte result = response[3];
                if (result != REPLY_ACK)
                    throw new FormatException("Error NACK" + result.ToString());
            }
        }

        private void ValidateAck(byte[] response)
        {
            if (response[2] != REPLY_ACK_NACK)
                throw new FormatException("Response type must be REPLY_ACK_NACK");
        }

        #endregion

        #region Transport

        #region Write Request

        private void WriteRequest(byte cmd, byte[] data)
        {
            byte[] req = GetRequest(cmd, data);
            _port.Write(req, 0, req.Length);
        }        

        private byte[] GetRequest(byte command, byte[] data)
        {
            MemoryStream msDest = new MemoryStream();

            msDest.WriteByte(FRAME_START); // стартовое условие            
            msDest.WriteByte(_frameIDGenerator.GetNextValue()); // идентификатор кадра
            msDest.WriteByte(command); // код комманды
            if (data != null)
                msDest.Write(data, 0, data.Length);
            msDest.WriteByte(0x00); // FCS, 2 байта
            msDest.WriteByte(0x00); // 
            msDest.WriteByte(FRAME_STOP); // стоповое условие

            byte[] result = msDest.ToArray();

            BitConverter.GetBytes(GetFCS(result)).CopyTo(result, result.Length - 3);

            return _byteStaffing.Encode(result);
        }

        #endregion

        #region Read Response

        private byte ReadByteFromPort()
        {
            return (byte)_port.ReadByte();
        }

        private byte[] ReadResponse()
        {
            while (ReadByteFromPort() != FRAME_START)
            { }

            MemoryStream msDest = new MemoryStream();

            msDest.WriteByte(FRAME_START);
            byte receivedByte;
            do
            {
                receivedByte = ReadByteFromPort();
                msDest.WriteByte(receivedByte);
            }
            while (receivedByte != FRAME_STOP);

            byte[] receivedBytes = _byteStaffing.Decode(msDest.ToArray());

            if (GetFCS(receivedBytes) != BitConverter.ToUInt16(receivedBytes, receivedBytes.Length - 3))
                throw new FormatException("FCS error");

            return receivedBytes;
        }

        #endregion

        private UInt16 GetFCS(byte[] data)
        {
            UInt32 fcs = 0xFFFF;
            for (int i = 1; i < data.Length - 3; i++)
            {
                UInt32 cb = data[i];
                UInt32 w = (cb ^ fcs) & 0xFF;
                for (int j = 0; j < 8; j++)
                {
                    if ((w & 1) != 0)
                    {
                        w >>= 1;
                        w ^= 0x8408;
                    }
                    else
                        w >>= 1;
                }
                fcs = w ^ (fcs >> 8);
            }
            fcs ^= 0xFFFFFFFF;
            return (UInt16)fcs;
        }

        #endregion

        #region Device Constants

        private const byte FRAME_START = 0xFD;
        private const byte FRAME_STOP = 0xFE;
        private const byte FRAME_STAFFED_BYTE = 0xFF;

        private const byte STAFFED_FRAME_STAFFED_BYTE = 0x00;
        private const byte STAFFED_FRAME_START = 0x02;
        private const byte STAFFED_FRAME_STOP = 0x01;

        private const byte REPLY_ACK_NACK = 0x2A;
        private const byte REPLY_ACK = 0x55;

        [Flags]
        private enum CardReaderSignals : byte
        {
            AllOff = 0x00,
            GreenOff = 0x00,
            GreenOn = 0x01,
            GreenBlink = 0x02,
            GreenBeeper = 0x03,
            RedOff = 0x00,
            RedOn = 0x04,
            RedBlink = 0x08,
            RedBeeper = 0x0C,
            BeeperOff = 0x00,
            BeeperOne = 0x10,
            BeeperDouble = 0x20,
            BeeperLong = 0x30,
            Default = 0x80
        }

        #endregion
    }

    public class CardReaderDeviceInfo
    {
        public string DeviceName { get; set; }
    }

Смотри, начиная с метода ExecuteCommand.
...
Рейтинг: 0 / 0
потоки в C#
    #38675520
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КЕсть решение проще.
...
Это ничего не меняет.
железобетонно!
...
Рейтинг: 0 / 0
потоки в C#
    #38675531
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КифирчикАлексей КЕсть решение проще.
...
Это ничего не меняет.
железобетонно!Два, на мой взгляд, наиболее правильных решения изложил выше, два раза. Уговаривать не собираюсь.
...
Рейтинг: 0 / 0
потоки в C#
    #38675651
Фотография fortibransa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roer Из строкового названия перечисления, получить само перечисление, например:
Код: c#
1.
serialPort.Parity = (System.IO.Ports.Parity)typeof(System.IO.Ports.Parity).GetField(stringParityType).GetValue(typeof(System.IO.Ports.Parity));
...
Рейтинг: 0 / 0
потоки в C#
    #38675666
Фотография fortibransa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По основному вопросу.
Я читаю по 1 байту (вообще сколько придет), но DataRessive срабатывает уже на одном байте(serialPort.ReceivedBytesThreshold = 1 по умолчанию) и если
Есть Старт байт(ы) и Стоп байт(ы) соответственно обрабатываю, те собираю пока не получу Стоп байт(байты). Это описано в протоколе обмена для конкретного устройства.
При этом работает таймер для таймаута.

Если известно только кол-во байт, то:
также собираю пока не придет нужное кол-во байт.
При этом работает таймер для таймаута.
или
поменять serialPort.ReceivedBytesThreshold = на нужное кол-во байт.
...
Рейтинг: 0 / 0
потоки в C#
    #38675745
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
видимо топикстартеру приходит что-то такое 16077419
Код: c#
1.
>-00.002


начало посылки он однозначно определить сможет, а вот окончание, видимо только по длине, либо по началу следующей посылки
...
Рейтинг: 0 / 0
потоки в C#
    #38675795
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кифирчиквидимо топикстартеру приходит что-то такое 16077419
Код: c#
1.
>-00.002


начало посылки он однозначно определить сможет, а вот окончание, видимо только по длине, либо по началу следующей посылкиЛибо по переводу строки, как это обычно принято в текстовых протоколах. Тогда достаточно связать StreamReader с компортом и сделать тупо ReadLine().
...
Рейтинг: 0 / 0
потоки в C#
    #38675797
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зы: StreamReader не нужен, в компорте есть встроенный ReadLine().
...
Рейтинг: 0 / 0
потоки в C#
    #38675800
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зы: Не забыть установить правильный SerialPort.Encoding
...
Рейтинг: 0 / 0
потоки в C#
    #38676839
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кифирчик , а как твоим классом воспользоваться?
...
Рейтинг: 0 / 0
потоки в C#
    #38676851
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в общем так вроде работает. сейчас с сервисом проверю


Код: 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.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
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.IO;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace MyComReader
{
    public partial class Form1 : Form
    {
        MyComReader three = new MyComReader();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
        }

        #region mycom
        internal class MyComReader
        {
            private SerialPort port;
            private System.Timers.Timer timer;
            private System.Threading.Thread thread;
            readonly EventWaitHandle wh = new AutoResetEvent(false);
            private bool doWork;
            int i = 0;
            string value = "";
            private string inData = "";

            public void ThreadStart()
            {
                doWork = true;
                thread = new Thread(Execute);
                thread.Start();
              

                this.timer = new System.Timers.Timer();
                this.timer.Enabled = true;
                this.timer.Interval = 5000;
                this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
                this.timer.AutoReset = true;
                this.timer.Start();
            }

            public void ThreadStop()
            {
                doWork = false;
                timer.Stop();
                wh.Set();
            }

            void Execute()
            {

                while (doWork)
                {
                    if (port == null)
                    {
                        port = new SerialPort("COM2", 9600);
                        port.DataReceived += port_DataReceived;
                    }
                    if (!port.IsOpen)
                        port.Open();

                    port.Write("#10\r");
                    wh.WaitOne();
                  
                }
                if (port.IsOpen)
                    port.Close();
            }

            void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                wh.Set();
            }
            
            
            void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                
                SerialPort sp = (SerialPort)sender;

                inData += sp.ReadExisting();
               // MessageBox.Show(i++.ToString() +  inData);
                value = inData;
                if (value.Length > 10 && value.Contains('\r'))
                {
                    MessageBox.Show(value + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss\t"));
                    inData = "";
                }

                // проверка, если в InData появилась полная строка - отрезаем кусок
                // и обрабатываем, а лучше в другой поток для обработки передаем

            }

           
        }
        #endregion

        private void button1_Click(object sender, EventArgs e)
        {
            
            three.ThreadStart();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            three.ThreadStop();
        }
    }
}



...
Рейтинг: 0 / 0
потоки в C#
    #38676881
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
c cервисом тоже работает
...
Рейтинг: 0 / 0
потоки в C#
    #38676976
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
млин как бы еще по образу и подобию tcp бы сделать
...
Рейтинг: 0 / 0
потоки в C#
    #38677060
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerмлин как бы еще по образу и подобию tcp бы сделать
tcp - не надо,
тебе же сообщения/пакеты нужны.

по по образу и подобию udp - делай
...
Рейтинг: 0 / 0
потоки в C#
    #38677071
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну я уже сделал))) а почему тсп не надо. я по протоколу тсп же общаюсь а не по удп
...
Рейтинг: 0 / 0
потоки в C#
    #38677073
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roer,

tcp на сообщения нарезать придётся
...
Рейтинг: 0 / 0
потоки в C#
    #38677327
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Они в футбол играют лучше чем вы пишете программы. Пойду отсюда...
...
Рейтинг: 0 / 0
потоки в C#
    #38677335
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вообще, tcp сделал так. может кому понадобится. может подскажите как правильней



Код: 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.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
        private void SelectCom()  //com port
        {
            try
            {
                NpgsqlConnection conn = new NpgsqlConnection(("Server=" + list[0] + ";Port=" + list[1] + ";User Id=" + list[2] + ";Password=" + list[3] + ";Database=" + list[4] + ";"));
                string sql = " SELECT   \"ID_TagName\" as id, \"F_ComPortIPAdress\",  \"F_ComQuery\", \"F_ComPort\",  \"F_ParseFunction\",                    \"F_TagReadTime\"           FROM ";
                sql += "\"SC_Tag\".\"T_TagName\" as tn,\"SC_Tag\".\"T_HardWareTag\" as hw , \"SC_Tag\".\"T_RealHardWare\" as rh            where  rh.\"ID_RealHardWare\" =   ";
                sql += "hw.\"F_RealHardWare_ID\"   and tn.\"F_HardWare_ID\" = hw.\"F_TagName_ID\"    and \"F_ServerName\"  =\'" + Environment.MachineName + "\' and \"F_ComPortIPAdress\" != '127.0.0.1' ";

                NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conn);
                ds.Reset();
                da.Fill(ds);
                dt = ds.Tables[0];

                if (ds.Tables[0] != null)
                {
                    InitAll();
                }

            }
            catch (Exception msg)
            {
                this.file.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss\t Select()") + msg.ToString());
                this.file.Flush();
                return;
            }
        }

        private void InitAll()
        {
            try
            {
                allListeners = new List<TcpComReader>();

                for (int xx = 0; xx < ds.Tables[0].Rows.Count; ++xx)
                {
                    string server = dt.Rows[xx][1].ToString();
                    string message = dt.Rows[xx][2].ToString() + "\r";                 
                    int port = Convert.ToInt32(dt.Rows[xx][3]);
                    int idcom = xx;
                    allListeners.Add(new TcpComReader(server, message, port, idcom));
                }
                min = Convert.ToInt32(dt.Rows[0][5]);
                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    if (Convert.ToInt32(dt.Rows[i][5]) < min)
                        min = Convert.ToInt32(dt.Rows[i][5]);
                }

                Go();
            }
            catch (Exception msg)
            {
                this.file.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss\t Select()") + msg.ToString());
                this.file.Flush();
                return;
            }
        }

        private void Go()
        {
            try
            {
                foreach (TcpComReader comListener in allListeners)
                {

                    comListener.ThreadStart();
                }

            }
            catch (Exception msg)
            {
                this.file.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss\t Select()") + msg.ToString());
                this.file.Flush();
                return;
            }
        }
        #region mycom
        internal class TcpComReader
        {

            private SerialPort port;
            private System.Timers.Timer timer;
            private System.Threading.Thread thread;
            readonly EventWaitHandle wh = new AutoResetEvent(false);
            private bool doWork;
            int i = 0;
            string value = "";
            private string inData = "";
            SerialPort _COM;
            string DataToSend;
            int IdCom;
            string ParseGlob = "";
            String Server ;
            int Port ;
            String msg;

            internal TcpComReader(String server, String message, Int32 port, Int32 idcom)
            {
                Server = server;
                Port = port;
                msg = message;
                IdCom = idcom;
            }

            public void ThreadStart()
            {
                doWork = true;
                thread = new Thread(Execute);
                thread.Start();


                this.timer = new System.Timers.Timer();
                this.timer.Enabled = true;
                this.timer.Interval = min;
                this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
                this.timer.AutoReset = true;
                this.timer.Start();
            }

            public void ThreadStop()
            {
                doWork = false;
                timer.Stop();
                wh.Set();
            }

            void Execute()
            {
                try
                {
                    while (doWork)
                    {
                        // Create a TcpClient.
                        // Note, for this client to work you need to have a TcpServer 
                        // connected to the same address as specified by the server, port
                        // combination.
                        TcpClient client = new TcpClient(Server, Port);

                        // Translate the passed message into ASCII and store it as a Byte array.
                        Byte[] data = Encoding.UTF8.GetBytes(msg);
                        // Get a client stream for reading and writing.


                        NetworkStream stream = client.GetStream();

                        // Send the message to the connected TcpServer. 
                        stream.Write(data, 0, data.Length);



                        // Receive the TcpServer.response.

                        // Buffer to store the response bytes.
                        data = new Byte[256];

                        Thread.Sleep(300);


                        // String to store the response ASCII representation.


                        // Read the first batch of the TcpServer response bytes.
                        Int32 bytes = stream.Read(data, 0, data.Length);
                        value = System.Text.Encoding.ASCII.GetString(data, 0, bytes);


                        NpgsqlConnection conn = new NpgsqlConnection(("Server=" + list[0] + ";Port=" + list[1] + ";User Id=" + list[2] + ";Password=" + list[3] + ";Database=" + list[4] + ";"));
                        conn.Open();
                        String Mystr = ("INSERT INTO " + list[5] + "(\"F_TagName_ID\",\"F_Value\",\"F_Date\")  VALUES (" + dt.Rows[IdCom][0].ToString() + ",\'" + value + "\',\'" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\'   )");
                        NpgsqlCommand command = new NpgsqlCommand(Mystr, conn);
                        int rowsaffected;
                        rowsaffected = command.ExecuteNonQuery();
                        conn.Close();
                        // Close everything.
                        stream.Close();
                        client.Close();
                        wh.WaitOne();
                    }
                }
                catch
                {
                    return;
                }
            }

            void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                wh.Set();
            }




        }
        #endregion

        private void button1_Click(object sender, EventArgs e)
        {
            SelectCom();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            foreach (TcpComReader comListener in allListeners)
            {
                comListener.ThreadStop();
            }
        }
    }
}




...
Рейтинг: 0 / 0
потоки в C#
    #38677362
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerвообще, tcp сделал так. может кому понадобится. может подскажите как правильней
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
                        // Receive the TcpServer.response.

                        // Buffer to store the response bytes.
                        data = new Byte[256];

                        Thread.Sleep(300);


                        // String to store the response ASCII representation.


                        // Read the first batch of the TcpServer response bytes.
                        Int32 bytes = stream.Read(data, 0, data.Length);
                        value = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

Это жесть вообще. Но какой смысл тебе подсказывать, если ты всё равно не читаешь? ( один , два )
...
Рейтинг: 0 / 0
потоки в C#
    #38679146
Кифирчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roer,
des1roerвообще, tcp сделал так. может кому понадобится. может подскажите как правильней
1. мне страшно если ты пример запустил в службе в таком виде как выложил здесь, там надо все обкладывать try..catch и при закрытии порта желательно не забывать отписываться от событий. это не проработает и недели.
2. то что ты сделал для TCP - это просто синхронно в отдельном потоке, не многим хуже будет работать код с простым таймером )))
если для TCP по образу и подобию, то есть асинхронно, будет примерно так
Код: 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.
   void Execute()
    {
           ...
            while (mustWork)
            {
                    sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    sockAsyncArgs = new SocketAsyncEventArgs();
                    sockAsyncArgs.Completed += sockAsyncArgs_Completed;
                    sockAsyncArgs.RemoteEndPoint = new DnsEndPoint(tcpEndPoint.Address.ToString(), tcpEndPoint.Port);

                    ConnectAsync(sockAsyncArgs);

                    while (mustWork && sockAsyncArgs.SocketError == SocketError.Success)
                    {
                        // после подмораживаем поток
                        wh.WaitOne();
                    }

            }//while (mustWork)

            if (sock != null)
                sock.Close();
            convertTimer.Stop();
            ...
        }

        private void ProcessConnect(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                WriteToConsole(string.Format("Подключились к Transas {0}...", e.RemoteEndPoint.ToString()));

                sockAsyncArgs.SetBuffer(buff, 0, buff.Length);

                ReceiveAsync(e);
                IsConnectionRefused = true;
            }
            else
            {

            }
        }

        private void ConnectAsync(SocketAsyncEventArgs e)
        {
            bool willRaiseEvent = sock.ConnectAsync(e);
            if (!willRaiseEvent)
                ProcessConnect(e);
        }
        
        private void ReceiveAsync(SocketAsyncEventArgs e)
        {
            bool willRaiseEvent = sock.ReceiveAsync(e);
            if (!willRaiseEvent)
                ProcessReceive(e);
        }

        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                // здесь кладем в очередь
                if (e.BytesTransferred > 0)
                {
                    lock (buffQueue)
                    {
                        byte[] newbuffer = new byte[e.BytesTransferred];
                        Array.Copy(e.Buffer, newbuffer, e.BytesTransferred);
                        // полученное складываю в очередь
                        buffQueue.Enqueue(newbuffer);
                    }
                }

                // запрашиваю следующий пакет
                ReceiveAsync(e);
            }
            else
            {
                WriteLogInfo(string.Format("Ошибка при получении пакета {0}...", e.RemoteEndPoint.ToString()));
                counterError.Inc(1);
            }
        }


и это пример как "поддерживать" TCP, не сказал бы что "тривиально"
посылать запросы и ловить ответы - это надо еще сверху накручивать

но у меня устройство не работает в режиме "запрос->ответ", я ему редко что передаю, мне в основном надо читать то что оно шлет,
и могут быть задержки по часу, от части по этому я сделал асинхронный прием.

у тебя же - "запрос->ответ" в течении 1..3 секунд, Алексей К тебе подсказал действительно заметно более простой и хороший вариант синхронного чтения
Код: 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.
        private byte[] ExecuteCommand(byte cmd, byte[] data)
        {
            WriteRequest(cmd, data);// ЗАПРОС
            byte[] response = ReadResponse(); //ПОЛУЧЕНИЕ ОТВЕТА
            ValidateFrameID(response);
            ValidateNack(response);
            return response;
        }
        private byte[] ReadResponse()
        {
            while (ReadByteFromPort() != FRAME_START)
            { }

            MemoryStream msDest = new MemoryStream();

            msDest.WriteByte(FRAME_START);
            byte receivedByte;
            do
            {
                receivedByte = ReadByteFromPort();
                msDest.WriteByte(receivedByte);
            }
            while (receivedByte != FRAME_STOP);

            byte[] receivedBytes = _byteStaffing.Decode(msDest.ToArray());

            if (GetFCS(receivedBytes) != BitConverter.ToUInt16(receivedBytes, receivedBytes.Length - 3))
                throw new FormatException("FCS error");

            return receivedBytes;
        }


тут полезно подсмотреть код парсинга, и допилить с учетом того что в твоем варианте нет FRAME_START
это реально проще чем асинхронное чтение, и будет правильно использовать одну функцию парсинга и для TCP и для Serial "приемников".
...
Рейтинг: 0 / 0
потоки в C#
    #38679192
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробую разобраться
...
Рейтинг: 0 / 0
потоки в C#
    #38680210
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Я не понял, причем тут потоки?
...
Рейтинг: 0 / 0
потоки в C#
    #38680215
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Thread.Sleep - зло. Кроме случая показа пользователю заставки своей супер-пупер программы
...
Рейтинг: 0 / 0
потоки в C#
    #38691014
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не хотелось создавать тему, спрошу тут.

Есть прога, которая опрашивает некое множество устройств по com-портам (допустим, 3 порта по 5 устройств на каждом). Для каждого порта я создаю отдельный поток, в котором для каждого устройства отправляю запрос и получаю ответ (или нет в течении таймаута). Теперь возникла необходимость добавить поддержку Ethernet-порта в программе для опроса множества устройств по TCP/IP. Допустим, мне нужно будет опросить 10 устройств с максимальной скоростью. Планирую работать через TcpClient. Мой первый опыт с ним. Имеет смысл опрашивать устройства в разных потоках? Как лучше построить работу с устройствами при условии минимизации времени на получение ответов и отсылку запросов?
...
Рейтинг: 0 / 0
потоки в C#
    #38691019
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pallaris для опроса множества устройств по TCP/IP. Допустим, мне нужно будет опросить 10 устройств с максимальной скоростью.
Socket.Select

и никаких лишних потоков.


а лучше асинхронный ввод вывод и для COM портов и для сокетов
...
Рейтинг: 0 / 0
потоки в C#
    #38691317
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а подробнее
...
Рейтинг: 0 / 0
потоки в C#
    #38693489
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропила лучше асинхронный ввод вывод и для COM портов и для сокетов

Речь о NetworkStream.BeginRead? Я чуть-чуть подкорректирую вводные:
1. Есть поток, который через одинаковые интервалы (допустим, 50 мс) опрашивает ряд устройств.
2. Есть поток (GUI), который по клику что-то на одно из устройств отправляет. При этом устройство на команду отвечает.

Как синхронизироваться? Т.е. первый поток ожидает одно, а ему приходит в ответ ответ от устройства по случаю 2? При работе с SerialPort я делал lock, посылал запрос, читал ответ и не парился - а тут как?
...
Рейтинг: 0 / 0
потоки в C#
    #38693949
Фотография des1roer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а покажите свои наработки с serial port
...
Рейтинг: 0 / 0
потоки в C#
    #38693965
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pallaris1. Есть поток, который через одинаковые интервалы (допустим, 50 мс) опрашивает ряд устройств.

в чём заключается опрос? Просто ожидание данных или посылка запроса с ожиданием ответа?


PallarisКак синхронизироваться?
Если ожидается ответ на команду - устройство исключается из общего опроса до получения ответа или истечения таймаута
...
Рейтинг: 0 / 0
потоки в C#
    #38693991
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилв чём заключается опрос? Просто ожидание данных или посылка запроса с ожиданием ответа?


Посылка запроса с ожиданием, да.

Если ожидается ответ на команду - устройство исключается из общего опроса до получения ответа или истечения таймаута

Исключить-то исключим, но как быть, если из другого потока устройству пошла управляющая команда (и на нее устройство тоже отвечает) в тот момент, как пошла посылка запроса из основного потока?
...
Рейтинг: 0 / 0
потоки в C#
    #38694000
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PallarisИсключить-то исключим, но как быть, если из другого потока устройству пошла управляющая команда (и на нее устройство тоже отвечает) в тот момент, как пошла посылка запроса из основного потока?

в очередь сукины дети (с)

поток gui ничего сам отправлять не должен, один поток должен заведовать вводом-выводом
...
Рейтинг: 0 / 0
потоки в C#
    #38694023
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилв очередь сукины дети (с)

поток gui ничего сам отправлять не должен, один поток должен заведовать вводом-выводом

Т.е. выходит заводим очередь сообщений для каждого объекта устройства, когда внешний поток хочет что-то отправить, он в эту очередь свое сообщение записывает. А поток ввода/вывода проходит по очереди, их выбрасывает в сеть, потом выполняет свои опросы (либо наоборот).

Блин, скорость отклика, т.е. срабатывания, очень важна. Боюсь, как бы из-за этой очереди не возникли потери времени. Тут без экспериментов не обойтись, наверное.
...
Рейтинг: 0 / 0
потоки в C#
    #38694029
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerа покажите свои наработки с serial port

Было бы что показывать
namespace SolarComm
{
public class CommPortSerial:CommPort,ISectioning
{

private int baudRate_ = 9600;
private int dataBits_ = 8;
private Parity portParity_ = Parity.None;
private StopBits stopBits_ = StopBits.One;
private int readTimeOut_ = 40;
private int writeTimeOut_ = 40;


private SerialPort sp = new SerialPort();

public int baudRate
{
set { baudRate_ = value; }
get { return baudRate_; }
}

public int dataBits
{
set { dataBits_ = value; }
get { return dataBits_; }
}

public Parity portParity
{
set { portParity_ = value; }
get { return portParity_; }
}

public StopBits stopBits
{
set { stopBits_ = value; }
get { return stopBits_; }
}

public int readTimeOut
{
set { readTimeOut_ = value; }
get { return readTimeOut_; }
}

public int writeTimeOut
{
set { writeTimeOut_ = value; }
get { return writeTimeOut_; }
}

public CommPortSerial()
{
name_ = "";
}



public override string ReadString(CommDevice dev_)
{

if (sp.IsOpen)
{
try
{
return sp.ReadLine();
}
catch
{

}
}
return String.Empty;
}

public override void ReadData(CommDevice dev_, ref byte[] response, int startIndex)
{
ReadData(dev_, ref response, startIndex, response.Length);
}

public override void ReadData(CommDevice dev_, ref byte[] response, int startIndex, int length)
{
if (response == null)
return;
if (sp.IsOpen)
{
//lock (lockObject_)
{
try
{

for (int i = startIndex; i < length; i++)
{
if (i < 0 || i >= response.Length)
break;
response[i] = (byte)(sp.ReadByte());
}

}
catch (Exception ex)
{

}
}
}
}

public override void ReadData(CommDevice dev_, ref byte[] response)
{
ReadData(dev_, ref response, 0, response.Length);
}

public override int ReadByte()
{

if (sp.IsOpen)
{
//lock (lockObject_)
{
try
{
return sp.ReadByte();
}
catch { }
}
}
return -1;
}

public override byte[] ReadData(CommDevice inDev,int length_)
{
base.ReadData(inDev,length_);
if (length_ > 0 && sp.IsOpen)
{
byte[] response = new byte[length_];
//lock (lockObject_)
{
try
{


for (int i = 0; i < response.Length; i++)
{
response[i] = (byte)(sp.ReadByte());
}

}
catch (Exception ex)
{

}
}
return response;
}

return null;

}

public override byte[] ReadData(CommDevice dev_)
{
base.ReadData(dev_);
if (sp.IsOpen)
{
int length_ = sp.BytesToRead;
if (length_ > 0)
{
byte[] response = new byte[length_];
//lock (lockObject_)
{
try
{

for (int i = 0; i < response.Length; i++)
{
response[i] = (byte)(sp.ReadByte());
}

}
catch (Exception ex)
{

}
}
return response;
}

}

return null;

}

public override void WriteData(CommDevice dev_,string msg_)
{

//lock (lockObject_)
{
base.WriteData(dev_,msg_);
DiscardOutputBuffer();
if (sp.IsOpen)
{

sp.WriteLine(msg_);


}
}
}

public override void WriteData(CommDevice dev_, byte[] buffer)
{
//lock (lockObject_)
{
base.WriteData(dev_,buffer);
DiscardOutputBuffer();

try
{
if (sp.IsOpen)
{

sp.Write(buffer, 0, buffer.Length);

}
}
catch (Exception ex)
{

}
}
}

public override void Open()
{
//lock (lockObject_)
{
base.Open();
try
{
if (!sp.IsOpen)
{
//Assign desired settings to the serial port:
sp.PortName = name_;
sp.BaudRate = baudRate_;
sp.DataBits = dataBits_;
sp.Parity = portParity_;
sp.StopBits = stopBits_;
sp.ParityReplace = (byte)0;
sp.ReadTimeout = readTimeOut_;
sp.WriteTimeout = writeTimeOut_;
sp.Open();
}
}
catch
{

}
}
if (sp.IsOpen)
{
isOpened_ = true;
}
else
{
isOpened_ = false;
}


}

public void DiscardInputBuffer()
{
if (sp.IsOpen)
{
//lock (lockObject_)
{
sp.DiscardInBuffer();
}
}
}

public void DiscardOutputBuffer()
{
if (sp.IsOpen)
{
//lock (lockObject_)
{
sp.DiscardOutBuffer();
}
}
}

public override void Prepare()
{
base.Prepare();
DiscardInputBuffer();
DiscardOutputBuffer();
}

public override void Close()
{
base.Close();

//Ensure port is opened before attempting to close:
if (sp.IsOpen)
{
try
{
sp.Close();
}
catch
{

}

}

if (sp.IsOpen)
{
isOpened_ = true;
}
else
{
isOpened_ = false;
}

}
}
}

...
Рейтинг: 0 / 0
потоки в C#
    #38694030
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
des1roerа покажите свои наработки с serial port
Забыл тег кода добавить, е-мое
Было бы что показывать
Код: 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.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
namespace SolarComm
{
    public class CommPortSerial:CommPort,ISectioning
    {
        
        private int baudRate_ = 9600;
        private int dataBits_ = 8;
        private Parity portParity_ = Parity.None;
        private StopBits stopBits_ = StopBits.One;
        private int readTimeOut_ = 40;
        private int writeTimeOut_ = 40;
        

        private SerialPort sp = new SerialPort();

        public int baudRate
        {
            set { baudRate_ = value; }
            get { return baudRate_; }
        }

        public int dataBits
        {
            set { dataBits_ = value; }
            get { return dataBits_; }
        }

        public Parity portParity
        {
            set { portParity_ = value; }
            get { return portParity_; }
        }

        public StopBits stopBits
        {
            set { stopBits_ = value; }
            get { return stopBits_; }
        }

        public int readTimeOut
        {
            set { readTimeOut_ = value; }
            get { return readTimeOut_; }
        }

        public int writeTimeOut
        {
            set { writeTimeOut_ = value; }
            get { return writeTimeOut_; }
        }

        public CommPortSerial()
        {
            name_ = "";
        }

        

        public override string ReadString(CommDevice dev_)
        {

            if (sp.IsOpen)
            {
                        try
                        {
                            return sp.ReadLine();
                        }
                        catch
                        { 
                            
                        }
            }
            return String.Empty;
        }

        public override void ReadData(CommDevice dev_, ref byte[] response, int startIndex)
        {
            ReadData(dev_, ref response, startIndex, response.Length);
        }

        public override void ReadData(CommDevice dev_, ref byte[] response, int startIndex, int length)
        {
            if (response == null)
                return;
            if (sp.IsOpen)
            {
                //lock (lockObject_)
                {
                    try
                    {

                        for (int i = startIndex; i < length; i++)
                        {
                            if (i < 0 || i >= response.Length)
                                break;
                            response[i] = (byte)(sp.ReadByte());
                        }

                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
        }

        public override void ReadData(CommDevice dev_, ref byte[] response)
        {
            ReadData(dev_, ref response, 0, response.Length);
        }

        public override int ReadByte()
        {
            
            if (sp.IsOpen)
            {
                //lock (lockObject_)
                {
                    try
                    {
                        return sp.ReadByte();
                    }
                    catch { }
                }
            }
            return -1;
        }

        public override byte[] ReadData(CommDevice inDev,int length_)
        {
            base.ReadData(inDev,length_);
            if (length_ > 0 && sp.IsOpen)
            {
                byte[] response = new byte[length_];
                //lock (lockObject_)
                {
                    try
                    {


                        for (int i = 0; i < response.Length; i++)
                        {
                            response[i] = (byte)(sp.ReadByte());
                        }
                        
                    }
                    catch (Exception ex)
                    {

                    }
                }
                return response;
            }

            return null;

        }

        public override byte[] ReadData(CommDevice dev_)
        {
            base.ReadData(dev_);
            if (sp.IsOpen)
            {
                int length_ = sp.BytesToRead;
                if (length_ > 0)
                {
                    byte[] response = new byte[length_];
                    //lock (lockObject_)
                    {
                        try
                        {

                            for (int i = 0; i < response.Length; i++)
                            {
                                response[i] = (byte)(sp.ReadByte());
                            }
                            
                        }
                        catch (Exception ex)
                        {

                        }
                    }
                    return response;
                }
                
            }

            return null;

        }

        public override void WriteData(CommDevice dev_,string msg_)
        {
            
            //lock (lockObject_)
            {
                base.WriteData(dev_,msg_);
                DiscardOutputBuffer();
                if (sp.IsOpen)
                {

                    sp.WriteLine(msg_);

                    
                }
            }
        }

        public override void WriteData(CommDevice dev_, byte[] buffer)
        {
            //lock (lockObject_)
            {
                base.WriteData(dev_,buffer);
                DiscardOutputBuffer();

                try
                {
                    if (sp.IsOpen)
                    {
                        
                        sp.Write(buffer, 0, buffer.Length);
                        
                    }
                }
                catch (Exception ex)
                {

                }
            }
        }

        public override void Open()
        {
            //lock (lockObject_)
            {
                base.Open();
                try
                {
                    if (!sp.IsOpen)
                    {
                        //Assign desired settings to the serial port:
                        sp.PortName = name_;
                        sp.BaudRate = baudRate_;
                        sp.DataBits = dataBits_;
                        sp.Parity = portParity_;
                        sp.StopBits = stopBits_;
                        sp.ParityReplace = (byte)0;
                        sp.ReadTimeout = readTimeOut_;
                        sp.WriteTimeout = writeTimeOut_;
                        sp.Open();
                    }
                }
                catch
                { 
                
                }
            }
            if (sp.IsOpen)
            {
                isOpened_ = true;
            }
            else
            {
                isOpened_ = false;
            }

            
        }

        public void DiscardInputBuffer()
        {
            if (sp.IsOpen)
            {
                //lock (lockObject_)
                {
                    sp.DiscardInBuffer();
                }
            }
        }

        public void DiscardOutputBuffer()
        {
            if (sp.IsOpen)
            {
                //lock (lockObject_)
                {
                    sp.DiscardOutBuffer();
                }
            }
        }

        public override void Prepare()
        {
            base.Prepare();
            DiscardInputBuffer();
            DiscardOutputBuffer();
        }

        public override void Close()
        {
            base.Close();

            //Ensure port is opened before attempting to close:
            if (sp.IsOpen)
            {
                try
                {
                    sp.Close();
                }
                catch
                {

                }

            }

            if (sp.IsOpen)
            {
                isOpened_ = true;
            }
            else
            {
                isOpened_ = false;
            }

        }
    }
}


...
Рейтинг: 0 / 0
потоки в C#
    #38694050
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PallarisА поток ввода/вывода проходит по очереди, их выбрасывает в сеть, потом выполняет свои опросы (либо наоборот).

не проходит, а постоянно ожидает, получает запрос - в порт/сокет асинхронно отправляет данные, ждёт дальше - запросов в очереди, завершения записи в порты/сокеты, прихода
данных портов/сокетов и следит за таймаутами
...
Рейтинг: 0 / 0
потоки в C#
    #38694134
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилне проходит, а постоянно ожидает, получает запрос - в порт/сокет асинхронно отправляет данные, ждёт дальше - запросов в очереди, завершения записи в порты/сокеты, прихода
данных портов/сокетов и следит за таймаутами

Я порассуждаю чуть-чуть:
1. Пусть в какой-то момент в очереди появилось три сообщения:
А. Считать данные с устройства
Б. Записать 1 в ячейку 0
В. Записать 0 в ячейку 1

2. Поток посылает асинхронно сообщения А, Б, В - объединив их в одну посылку.
3. По завершению отправки считываем входной буфер.
4. Распарсиваем байты на три блока и сохраняем ответы. Причем ответы нужно сопоставить с посылками, ведь теоретически на посылку Б устройство могло не ответить, и нужно понять, что там, где ожидался ответ на Б - пришел ответ на В.
5. Что, если на момент считывания входного буфера еще не все данные до нас дошли? Продолжаем ждать в течении какого-то таймаута?
6. Ждем новых посылок в очереди

Прокомментируй пожалуйста.
...
Рейтинг: 0 / 0
потоки в C#
    #38694195
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pallaris,

всё от устройства зависит.
одни устройства могут только по очереди команды обрабатывать( пока клиенту устройство ответ не отправило - устройство команды игнорирует)
другие могут принять несколько команд( да хоть в UART своём держать) и ответы поочереди выдать

третьи имеют возможность пометить команды тэгом и в произвольном порядке завершить выполнение (в ответном сообщении будет присутствовать этот тэг)

По третьему варианту работают, например, PTP/MTP устройства, они ещё и асинхронные события могут инициировать
...
Рейтинг: 0 / 0
потоки в C#
    #38694231
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

тогда получается в общем случае не имеет смысла одно устройство спамить запросами, а нужно отправить один запрос из очереди и дождаться ответа либо таймаута?
...
Рейтинг: 0 / 0
76 сообщений из 76, показаны все 4 страниц
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / потоки в C#
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]