С Новым годом! Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
1

Одновременная передача данных в виде двух массивов через буфер обмена

22.05.2019, 10:34. Показов 2191. Ответов 28
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день, пишу программу корреляционного расходомера на основе sdk виртуального осциллографа и столкнулся с проблемой одновременной передачи входящих данных с двух каналов. Проблема заключается в следующем: имеется два входящих сигнала и, соответственно, два одновременно и беспрерывно обновляющихся массива входящих данных, которые нужно одновременно передать на другое приложение для последующей обработки. Как это правильно сделать? Написал что-то подобное, но не уверен в правильности работы:
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
void CHard::SourceToDisplay(USHORT* pData,ULONG nDataLen,USHORT nCH)
{
    int j = 1;
    for(ULONG i=0;i<nDataLen;i++)
    {
        *(m_pSrcData[nCH]+i) = *(pData+i)-(MAX_DATA - m_nLeverPos[nCH]);
    }
    if(OpenClipboard(NULL))
            {
                std::stringstream str;
                str << *(m_pSrcData[nCH]);
                for (j=1; j < nDataLen; j++)
                {
                    str << " " << *(m_pSrcData[nCH] + j);
                } //преобразование массива ushort в string
                std::string str2 =str.str();
                HGLOBAL hgBuffer;
         EmptyClipboard(); //очищаем буфер
         hgBuffer= GlobalAlloc(GMEM_DDESHARE, str2.size()+1);
         std::string chBuffer;
         chBuffer = (LPTSTR)GlobalLock(hgBuffer);
         chBuffer= str2;
         GlobalUnlock(hgBuffer);
         SetClipboardData(CF_TEXT, hgBuffer);
         CloseClipboard();
            }
}
Приложение, которое принимает и обрабатывает данные, еще не написано, но сразу хотел бы спросить, как лучше все это скомпоновать, можно ли написать это приложение на c# с его WPF (и как тогда правильно связать со вторым приложением)? В данном приложении должна будет быть кнопка, по нажатию которой запускается второй проект и начинается прием данных с осциллографа и передача их на первый проект.
Используется Visual Studio 2010.
0
Programming
Эксперт
9485 / 562 / 19
Регистрация: 12.04.2006
Сообщений: 11,671
Блог
22.05.2019, 10:34
Ответы с готовыми решениями:

Передача файла через буфер обмена RDP и его запуск
вот код он входит в rdp надо добавить в него что бы он после входа брал файл передавал его в rdp...

Копирование через буфер обмена из 2х полей формы и вставка данных в другую форму
Всем очень добрый день! Подскажите пожалуйста, можно ли реализовать одновременное копирование...

Буфер обмена(получение и передача информации)
Всем привет. Мне необходимо получить данные из буфера обмена(данные могут быть любые, картинка,...

Передача параметра в буфер обмена c JavaScript
Пользовательская форма вызывается по щелчку на веб-странице. Эта форма с кнопками написана на...

28
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
22.05.2019, 22:43 2
narsky, я бы не стал использовать буфер обмена для непрерывного обмена данными между процессами.
Есть много других вариантов:
1. Общая область памяти (shared memory), доступ к которой синхронизируется мьютексом;
2. Пайпы (pipes);
3. Сокеты (sockets);
4. ...

Добавлено через 8 минут
Цитата Сообщение от narsky Посмотреть сообщение
можно ли написать это приложение на c# с его WPF (и как тогда правильно связать со вторым приложением)?
Можно использовать любой из вышеперечисленных механизмов.

Если одно приложение запускает другое, то лучше всего подойдут пайпы. Приложения могут запускаться на разных компьютерах, то подойдут только сокеты. Общая область памяти по своей природе почти ничем не отличается от передачи данных через файл.
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
22.05.2019, 23:22  [ТС] 3
nonedark2008, спасибо, впервые слышу про такой механизм, где можно почитать / поискать наиболее полезные примеры использования пайпов?
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
23.05.2019, 00:15 4
Цитата Сообщение от narsky Посмотреть сообщение
где можно почитать / поискать наиболее полезные примеры использования пайпов?
Где почитать зависит от твоего текущего уровня. Я бы начал с документации на MSDN, там есть информация и примеры для C/C++/C#.

А поискать можно в поисковике по ключевым словам вида: winapi, C#, pipes, пайпы, каналы и т.п.
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
31.05.2019, 17:11  [ТС] 5
Реализовал (как мне кажется) передачу данных с помощью пайпа между двумя приложениями, но при попытке вывода на экран первого значения постоянно меняющегося массива возникает следующая ошибка. С чем это может быть связано, как исправить? Прикладываю код формы первого и основного приложения, который принимает по пайпу массив данных, и дополненный файл второго приложения (один из SDK), с которого и отправляются данные.
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
#include <windows.h>
#define BUF_4K_LEN                  0x1000
 
 
#pragma once
 
namespace Приложение {
 
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
 
    /// <summary>
    /// Summary for Form1
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
              
 
        }
        
        
        
 
    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }
 
    private: System::Windows::Forms::Button^  button1;
    private: System::Windows::Forms::Timer^  timer1;
    private: System::Windows::Forms::Label^  label1;
    private: System::ComponentModel::IContainer^  components;
    protected: 
 
    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
 
 
#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->components = (gcnew System::ComponentModel::Container());
            this->button1 = (gcnew System::Windows::Forms::Button());
            this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
            this->label1 = (gcnew System::Windows::Forms::Label());
            this->SuspendLayout();
            // 
            // button1
            // 
            this->button1->Location = System::Drawing::Point(277, 174);
            this->button1->Name = L"button1";
            this->button1->Size = System::Drawing::Size(75, 23);
            this->button1->TabIndex = 1;
            this->button1->Text = L"button1";
            this->button1->UseVisualStyleBackColor = true;
            this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
            // 
            // timer1
            // 
            this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
            // 
            // label1
            // 
            this->label1->AutoSize = true;
            this->label1->Location = System::Drawing::Point(463, 183);
            this->label1->Name = L"label1";
            this->label1->Size = System::Drawing::Size(35, 13);
            this->label1->TabIndex = 2;
            this->label1->Text = L"label1";
            // 
            // Form1
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(593, 287);
            this->Controls->Add(this->label1);
            this->Controls->Add(this->button1);
            this->Name = L"Form1";
            this->Text = L"Form1";
            this->ResumeLayout(false);
            this->PerformLayout();
 
        }
#pragma endregion
 
        Int32 timeCounter; 
        USHORT** pReadData;
        ULONG nReadDataLen;
        
        
        
HANDLE   hNamedPipe;
 
[STAThreadAttribute]
void launch() {
    // запустить приложение
    
 
    LPCWSTR pipeName = L"\\\\.\\pipe\\demo_pipe";
    nReadDataLen = BUF_4K_LEN;
    pReadData = new USHORT *[4];
    for(int i=0;i<4;i++)
    {
        pReadData[i] = new USHORT[nReadDataLen];
        memset(pReadData[i],0,nReadDataLen*sizeof(USHORT));//
    }
    hNamedPipe = CreateFile(
    pipeName,          // имя канала
    GENERIC_READ | GENERIC_WRITE,       // читаем и записываем в канал
    FILE_SHARE_READ | FILE_SHARE_WRITE, // разрешаем чтение и запись 
    NULL,                  // безопасность по умолчанию
    OPEN_EXISTING,         // открываем существующий канал
    FILE_ATTRIBUTE_NORMAL, // атрибуты по умолчанию
    NULL);
    
}
void data() {
    DWORD   dwBytesRead;
    
    
    ReadFile(
    hNamedPipe,      // дескриптор канала
    pReadData,      // данные
    sizeof(pReadData) + 1,  // размер данных
&dwBytesRead,    // количество записанных байтов
    NULL);
    
}
        
 
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
                
 launch();
             
        timer1->Interval = 1000;
        timer1->Enabled = true;
 
             }
    private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
                 data();
                unsigned short ar = pReadData[0][1];
        label1->Text = ar.ToString();
             }
    };
}
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
// Hard.cpp: implementation of the CHard class.
//
//////////////////////////////////////////////////////////////////////
 
#include "stdafx.h"
#include "VCDSO.h"
#include "Hard.h"
#include <iostream>
#include <sstream>
#include <string.h>
#include <windows.h>
using namespace std;
 
 
 
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
 
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
 
CHard::CHard()
{
    m_nLeverPos[CH1] = 192;
    m_nLeverPos[CH2] = 160;
    m_nLeverPos[CH3] = 96;
    m_nLeverPos[CH4] = 64; 
    ULONG i = 0;
    m_nDeviceIndex = 0;
    m_nDeviceNum = 0;
    for(i=0;i<MAX_CH_NUM;i++)
    {
        m_pSrcData[i] = new short[BUF_4K_LEN];
    }
    m_clrRGB[CH1] = RGB(255,255,0);
    m_clrRGB[CH2] = RGB(0,255,255);
    m_clrRGB[CH3] = RGB(255,0,255);
    m_clrRGB[CH4] = RGB(0,255,0);
    m_nTimeDIV = 12;
    m_nYTFormat = YT_NORMAL;
    m_stControl.nCHSet = 0x0F;//ЛщУРНЁµАґтїЄ
    m_stControl.nTimeDIV = m_nTimeDIV;//Factory Setup
    m_stControl.nTriggerSource = CH1;//НЁµА1ОЄґҐ·ўНЁµА
    m_stControl.nHTriggerPos = 50;//Л®ЖЅґҐ·ўО»ЦГЈЁ0-100Ј©
    m_stControl.nVTriggerPos = m_nLeverPos[CH1];//ґ№Ц±ґҐ·ўО»ЦГєННЁµА1ПаН¬
    m_stControl.nTriggerSlope = RISE;//±ЯСШґҐ·ўµДґҐ·ў·ЅКЅЈєЙПЙэСШ
    m_stControl.nBufferLen = BUF_4K_LEN;//ІЙјЇЙо¶И
    m_stControl.nReadDataLen = BUF_4K_LEN;//¶БИЎі¤¶И<=ІЙјЇЙо¶И
    m_stControl.nAlreadyReadLen = 0;//Ц»ФЪЙЁГи№ц¶ЇЗйїцПВУРР§Ј¬УГАґјЗВјТСѕ*¶БИЎµДі¤¶И
    m_stControl.nALT = 0;//Factory Setup
    for(i=0;i<MAX_CH_NUM;i++)
    {
        RelayControl.bCHEnable[i] = 1;
        RelayControl.nCHVoltDIV[i] = 8;
        RelayControl.nCHCoupling[i] = DC;
        RelayControl.bCHBWLimit[i] = 0;
    }   
    RelayControl.nTrigSource = CH1;
    RelayControl.bTrigFilt = 0;
    RelayControl.nALT = 0;
    m_nTriggerMode = EDGE;
    m_nTriggerSlope = RISE;
    m_nTriggerSweep = AUTO;
 
    m_bCollect=TRUE;
    m_nReadOK = 0;
 
 
}
 
CHard::~CHard()
{
 
}
 
void CHard::Init()
{
    m_nDeviceIndex = 0;
    dsoInitHard(m_nDeviceIndex);//УІјюіхКј»Ї
    dsoHTADCCHModGain(m_nDeviceIndex,4);//ЙиЦГУЙНЁµАДЈКЅТэЖрµД·щ¶ИРЮХэ
 
    dsoHTSetSampleRate(m_nDeviceIndex,m_nYTFormat,&RelayControl,&m_stControl);//ЙиЦГІЙСщВК
    dsoHTSetCHAndTrigger(m_nDeviceIndex,&RelayControl,m_stControl.nTimeDIV);//ЙиЦГНЁµАїЄ№ШєНµзС№µµО»
    dsoHTSetRamAndTrigerControl(m_nDeviceIndex,m_stControl.nTimeDIV,m_stControl.nCHSet,m_stControl.nTriggerSource,0);//ЙиЦГґҐ·ўФґ
    for(int i=0;i<MAX_CH_NUM;i++)
    {
        dsoHTSetCHPos(m_nDeviceIndex,RelayControl.nCHVoltDIV[i],m_nLeverPos[i],i,4);
    }
    dsoHTSetVTriggerLevel(m_nDeviceIndex,m_nLeverPos[CH1],4);
    switch (m_nTriggerMode) {//ґҐ·ўЙиЦГ
        case EDGE:
            dsoHTSetTrigerMode(m_nDeviceIndex,m_nTriggerMode,m_stControl.nTriggerSlope,DC);
            break;
            /*
        case VIDEO:
            {
            double dbVolt=m_dbVoltDIV[RelayControl.nCHVoltDIV[m_nALTSelCH]];
            short nPositive=nVideoPositive==POSITIVE?TRIGGER_VIDEO_POSITIVE:TRIGGER_VIDEO_NEGATIVE;
            WORD nTriggerLevel=255-GetCHLeverPos(m_nALTSelCH)+short((256*nPositive)/(dbVolt*V_GRID_NUM)+0.5);
            dsoHTSetTrigerMode(m_nDeviceIndex,m_nTriggerMode,m_stControl.nTriggerSlope,m_Trigger.m_nTriggerCouple);
            dsoHTSetVideoTriger(m_nDeviceIndex,nVideoStandard,nVideoSyncSelect,nVideoHsyncNumOption,nVideoPositive,nTriggerLevel,GetLogicTriggerSource(m_nALTSelCH));
            break;}
        case PULSE:
            dsoHTSetTrigerMode(m_nDeviceIndex,m_nTriggerMode,m_stControl.nTriggerSlope,m_Trigger.m_nTriggerCouple);
            dsoHTSetPulseTriger(m_nDeviceIndex,nPW,nPWCondition);
            break;
        case FORCE:
            dsoHTSetTrigerMode(m_nDeviceIndex,m_nTriggerMode,m_stControl.nTriggerSlope,m_Trigger.m_nTriggerCouple);
            */
        default:
            break;
       
}hNamedPipe = CreateNamedPipe(
    "\\\\.\\pipe\\demo_pipe",          // имя канала
     PIPE_ACCESS_DUPLEX,        // читаем из канала и пишем в канал
    PIPE_TYPE_MESSAGE | PIPE_WAIT,   // синхронная передача сообщений
    1,         // максимальное количество экземпляров канала 
    0,         // размер выходного буфера по умолчанию
    0,         // размер входного буфера по умолчанию
    INFINITE,  // клиент ждет связь бесконечно долго
    NULL       // безопасность по умолчанию
    );
  ConnectNamedPipe(
    hNamedPipe,    // дескриптор канала
    NULL      // связь синхронная
    );
    ddsSetCmd(m_nDeviceIndex,0);
ddsSDKSetFre(m_nDeviceIndex,30000);
ddsSDKSetAmp(m_nDeviceIndex,3500);
ddsSDKSetOffset(m_nDeviceIndex,-500);
ddsSDKSetWaveType(m_nDeviceIndex,0);
ddsSetOnOff(m_nDeviceIndex,1);
 
  
  
 
 
}
void CHard::ReadData()
{
    int i=0;
    USHORT* pReadData[MAX_CH_NUM];
    
    for(i=0;i<MAX_CH_NUM;i++)
    {
        pReadData[i] = new USHORT[m_stControl.nReadDataLen];
        memset(pReadData[i],0,m_stControl.nReadDataLen*sizeof(USHORT));//
    } //заменяем нулями
    m_nReadOK = dsoHTGetData(m_nDeviceIndex,pReadData[CH1],pReadData[CH2],pReadData[CH3],pReadData[CH4],&m_stControl);//ГїНЁµАiµЪjёцµгµДКµјКµзС№Цµ=(pReadData[i][j]-m_nLeverPos[i])*8*µзС№Цµ/255
    
    if(m_nReadOK == 1)
    {
        for(i=0;i<MAX_CH_NUM;i++)
        {
            SourceToDisplay(pReadData[i],m_stControl.nReadDataLen,i);//ОЄБЛ·Ѕ±гПФКѕ
            
            
 
 
            /*if(OpenClipboard(NULL))
            {
                char source [4096*sizeof(USHORT)+4095];
                for (j=0; j<m_stControl.nReadDataLen; j++)
                {
                    itoa(
                }
                HGLOBAL hgBuffer;
         EmptyClipboard(); //очищаем буфер
         hgBuffer= GlobalAlloc(GMEM_DDESHARE, sizeof(pReadData[i]));//выделяем память
         USHORT* chBuffer;
         chBuffer= (USHORT*)GlobalLock(hgBuffer); //блокируем память
         strcpy(chBuffer, LPCSTR(source));
         GlobalUnlock(hgBuffer);//разблокируем память
         SetClipboardData(CF_TEXT, hgBuffer);//помещаем текст в буфер обмена
         CloseClipboard(); //закрываем буфер обмена
            }*/
        }
        WriteFile(hNamedPipe,      // дескриптор канала
                 pReadData,      // данные
    sizeof(pReadData)+1,  // размер данных
    &dwBytesWritten, // количество записанных байтов
    NULL)  ;        // синхронная запись
    }
    
 
       /* wchar_t * lptstrCopy = NULL; 
        HGLOBAL hglbCopy = NULL; 
 
        if( !OpenClipboard() ) 
            return; 
 
        EmptyClipboard(); 
 
        hglbCopy = GlobalAlloc( GMEM_MOVEABLE, (data.size()+1)*2 ); 
        if (hglbCopy == NULL) 
        { 
            CloseClipboard(); 
            return; 
        } 
 
        lptstrCopy = (wchar_t*)GlobalLock(hglbCopy); 
 
        memcpy(lptstrCopy, data.c_str(), data.size()*2);
        lptstrCopy[data.size()] = 0;
        GlobalUnlock(hglbCopy); 
 
        SetClipboardData(CF_UNICODETEXT, hglbCopy); 
 
        CloseClipboard();*/
 
    for(i=0;i<MAX_CH_NUM;i++)
    {
        delete pReadData[i];
    }
}
 
void CHard::SourceToDisplay(USHORT* pData,ULONG nDataLen,USHORT nCH)
{
    int j = 1;
    for(ULONG i=0;i<nDataLen;i++)
    {
        *(m_pSrcData[nCH]+i) = *(pData+i)-(MAX_DATA - m_nLeverPos[nCH]);
    }
    /*if(OpenClipboard(NULL))
            {
                std::stringstream str;
                str << *(m_pSrcData[nCH]);
                for (j=1; j < nDataLen; j++)
                {
                    str << " " << *(m_pSrcData[nCH] + j);
                }
                std::string str2 =str.str();
                HGLOBAL hgBuffer;
         EmptyClipboard(); //очищаем буфер
         hgBuffer= GlobalAlloc(GMEM_DDESHARE, str2.size()+1);//выделяем память
         std::string chBuffer;
         chBuffer = (LPTSTR)GlobalLock(hgBuffer); //блокируем память
         chBuffer= str2;
         GlobalUnlock(hgBuffer);//разблокируем память
         SetClipboardData(CF_TEXT, hgBuffer);//помещаем текст в буфер обмена
         CloseClipboard(); //закрываем буфер обмена
            }*/
}
Миниатюры
Одновременная передача данных в виде двух массивов через буфер обмена   Одновременная передача данных в виде двух массивов через буфер обмена  
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
31.05.2019, 22:21 6
Цитата Сообщение от narsky Посмотреть сообщение
C++
1
2
3
4
5
6
ReadFile(
* * hNamedPipe, * * *// дескриптор канала
* * pReadData, * * *// данные
* * sizeof(pReadData) + 1, *// размер данных
&dwBytesRead, * *// количество записанных байтов
* * NULL);
Ты перезаписываешь указатели, расположенные в pReadData, соответственно pReadData[0] будет указывать куда-то не туда.

Добавлено через 1 минуту
Цитата Сообщение от narsky Посмотреть сообщение
sizeof(pReadData) + 1
Мне кажется, что эта команда возвращает не тот "размер данных", что ты хочешь.

Добавлено через 2 минуты
Цитата Сообщение от narsky Посмотреть сообщение
WriteFile(hNamedPipe, * * *// дескриптор канала
* * * * * * * * *pReadData, * * *// данные
* * sizeof(pReadData)+1, *// размер данных
* * &dwBytesWritten, // количество записанных байтов
* * NULL) *;
И записываешь ты что-то не то. Тебе нужно передавать и принимать именно данные, а не случайные указатели, которые на эти данные указывают.
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
01.06.2019, 08:07  [ТС] 7
Цитата Сообщение от nonedark2008 Посмотреть сообщение
И записываешь ты что-то не то. Тебе нужно передавать и принимать именно данные, а не случайные указатели, которые на эти данные указывают.
Т.е. нужно перед записью создать двумерный массив, в который сперва закинуть данные с указателей, а потом передать их?
Цитата Сообщение от nonedark2008 Посмотреть сообщение
Ты перезаписываешь указатели, расположенные в pReadData, соответственно pReadData[0] будет указывать куда-то не туда.
И то же самое здесь, только еще нужно добавить удаление памяти динамического массива в конце, правильно? Или как лучше это сделать?
Цитата Сообщение от nonedark2008 Посмотреть сообщение
Мне кажется, что эта команда возвращает не тот "размер данных", что ты хочешь.
Она возвращает же все байты двумерного массива, разве нет? Теоретически, мне нужна лишь их половина (т.е. всего 2 канала из 4), тогда можно записать так, правильно? Или что не так?
C++
1
sizeof(pReadData)/2
и еще такой вопрос, а нормально ли будет пайп работать с циклом? К примеру, будут ли правильно передаваться данные в таком коде?
C++
1
2
3
4
5
6
7
8
9
for (int i = 0; i<2; i++)
{
ReadFile(
* * hNamedPipe, * * *// дескриптор канала
* * pReadData[i], * * *// данные
* * sizeof(pReadData[i]) + 1, *// размер данных
&dwBytesRead, * *// количество записанных байтов
* * NULL);
}
C++
1
2
3
4
5
6
7
8
for (int i = 0; i<2; i++)
{
WriteFile(hNamedPipe, * * *// дескриптор канала
* * * * * * * * *pReadData[i], * * *// данные
* * sizeof(pReadData[i])+1, *// размер данных
* * &dwBytesWritten, // количество записанных байтов
* * NULL) *;
}
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
01.06.2019, 09:23 8
Цитата Сообщение от narsky Посмотреть сообщение
двумерный массив
Я думаю, что ты запутался в массивах.
В C++ двумерный массив можно создать вот так:
C++
1
int ppArr[5][5];
Его особенностью является то, что в памяти он располагается непрерывно, и по сути ничем не отличается от int pArr[5 * 5];, а его размер - sizeof(ppArr) == 25 * sizeof(int).
В твоем же случае история другая:
C++
1
2
3
4
int **ppArr;
ppArr = new int *[5];
for (int i = 0; i < 5; ++i)
    ppArr[i] = new int[5];
Создается массив указателей int *, каждому из которых мы присваиваем какое-то значение. Массив указателей и блоки данных, на которые эти указатели указывают, скорее всего хаотично разбросаны по памяти. Ни о какой непрерывности тут уже речи не идет, да и sizeof(ppArr) == sizeof(int **).

Дело в том, что sizeof(...) возвращает размер типа, а не то, что ты себе придумал. В первом случае компилятор знает, что типом переменной является int[5][5], поэтому sizeof вернет 25*sizeof(int). А вот во втором случае тип - int **, и, соответственно, sizeof вернет sizeof(int**).

Добавлено через 2 минуты
Цитата Сообщение от narsky Посмотреть сообщение
и еще такой вопрос, а нормально ли будет пайп работать с циклом?
Да, будет. Пайп - это "трубка". Суешь с одного конца, забираешь из другого в том же порядке, в котором данные были отправлены.

Цитата Сообщение от narsky Посмотреть сообщение
К примеру, будут ли правильно передаваться данные в таком коде?
Нет, из-за того, что sizeof применяешь некорректно.
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
01.06.2019, 11:42  [ТС] 9
nonedark2008, я действительно немного запутался @_@
Получается, что sizeof лучше не применять к динамическому массиву. Тогда лучше действительно будет создать два новых массива (их размерность известна) и их уже передавать через пайп?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
USHORT ReadData[4][4096];
... // получение данных в pReadData
for (int i =0; i<4; i++)
{
ReadData[i] = pReadData[i];
}
for (int i = 0; i < 4; i++)
{
WriteFile(
* * hNamedPipe, * * *// дескриптор канала
* * ReadData[i], * * *// данные
* * sizeof(ReadData[i]) + 1, *// размер данных
&dwBytesWritten, * *// количество записанных байтов
* * NULL);
}
Ну и аналогично для чтения пайпа.

Или вот так будет правильнее, без создания дополнительных массивов:
C++
1
2
3
4
5
6
WriteFile(hNamedPipe,      // дескриптор канала
                 *pReadData,      // данные
     m_stControl.nReadDataLen*sizeof(USHORT),  // размер данных, m_stControl.nReadDataLen = 4096
    &dwBytesWritten, // количество записанных байтов
    NULL)  ;        // синхронная запись
    }
И аналогично для чтения.

Добавлено через 43 минуты
upd для sizeof - так будет правильнее, я думаю:
C++
1
MAX_CH_NUM*m_stControl.nReadDataLen*sizeof(USHORT),
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
01.06.2019, 11:50 10
Цитата Сообщение от narsky Посмотреть сообщение
Или вот так будет правильнее, без создания дополнительных массивов
Типа того. Просто следи, указатель на какие данные и в каком объеме ты предаешь.
В твоем самом первом примере достаточно было сделать следующее:
C++
1
2
3
4
5
6
// Запись
for (int i = 0; i < CH_NUM; ++i)
    WriteFile(hNamedPipe, pReadData[i], nReadDataLen*sizeof(USHORT), &dwBytesWritten, NULL);
// Чтение
for (int i = 0; i < CH_NUM; ++i)
    ReadFile(hNamedPipe, pReadData[i], nReadDataLen*sizeof(USHORT),&dwBytesRead, NULL);
С точностью до того, что я не знаю, что твой код должен делать на практике. Еще бы не помешало проверять коды ошибок, возвращаемые функциями WinAPI.
1
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
01.06.2019, 12:04  [ТС] 11
Цитата Сообщение от nonedark2008 Посмотреть сообщение
С точностью до того, что я не знаю, что твой код должен делать на практике. Еще бы не помешало проверять коды ошибок, возвращаемые функциями WinAPI.
Спасибо! Я займусь этим позже, сперва я хотел просто реализовать передачу данных и проверить все на работоспособность (к сожалению, прибора нет под рукой, так что это можно будет сделать лишь на неделе), а потом уже заняться проверками и дальнейшим написанием программы : )
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
03.06.2019, 10:12  [ТС] 12
Коды поправил, но по каким-то причинам форма первого приложения, принимающего данные, после начала передачи данных просто зависает и ни на что не реагирует. С чем это может быть связано? (на данный момент я проверяю обновление данных label1 в форме)
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
#include <windows.h>
#define PI  3.1415926535897932384626433832795
#define BUF_4K_LEN                  0x1000
 
 
#pragma once
 
namespace Приложение {
 
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
 
    /// <summary>
    /// Summary for Form1
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
              
 
        }
        
        
        
 
    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }
    private: System::Windows::Forms::Button^  button1;
    protected: 
 
    protected: 
 
 
    private: System::Windows::Forms::Timer^  timer1;
    private: System::Windows::Forms::Label^  label1;
    private: System::Windows::Forms::Button^  button2;
    private: System::Windows::Forms::TextBox^  textBox1;
    private: System::Windows::Forms::TextBox^  textBox2;
    private: System::Windows::Forms::Label^  label2;
    private: System::Windows::Forms::Label^  label3;
    private: System::Windows::Forms::Label^  label4;
    private: System::ComponentModel::IContainer^  components;
    protected: 
 
    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
 
 
#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->components = (gcnew System::ComponentModel::Container());
            this->button1 = (gcnew System::Windows::Forms::Button());
            this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
            this->label1 = (gcnew System::Windows::Forms::Label());
            this->button2 = (gcnew System::Windows::Forms::Button());
            this->textBox1 = (gcnew System::Windows::Forms::TextBox());
            this->textBox2 = (gcnew System::Windows::Forms::TextBox());
            this->label2 = (gcnew System::Windows::Forms::Label());
            this->label3 = (gcnew System::Windows::Forms::Label());
            this->label4 = (gcnew System::Windows::Forms::Label());
            this->SuspendLayout();
            // 
            // button1
            // 
            this->button1->Location = System::Drawing::Point(225, 173);
            this->button1->Name = L"button1";
            this->button1->Size = System::Drawing::Size(75, 23);
            this->button1->TabIndex = 1;
            this->button1->Text = L"Start";
            this->button1->UseVisualStyleBackColor = true;
            this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
            // 
            // timer1
            // 
            this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
            // 
            // label1
            // 
            this->label1->AutoSize = true;
            this->label1->Location = System::Drawing::Point(463, 183);
            this->label1->Name = L"label1";
            this->label1->Size = System::Drawing::Size(35, 13);
            this->label1->TabIndex = 2;
            this->label1->Text = L"label1";
            // 
            // button2
            // 
            this->button2->Location = System::Drawing::Point(348, 172);
            this->button2->Name = L"button2";
            this->button2->Size = System::Drawing::Size(75, 23);
            this->button2->TabIndex = 3;
            this->button2->Text = L"Stop";
            this->button2->UseVisualStyleBackColor = true;
            this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);
            // 
            // textBox1
            // 
            this->textBox1->Location = System::Drawing::Point(448, 34);
            this->textBox1->Name = L"textBox1";
            this->textBox1->Size = System::Drawing::Size(100, 20);
            this->textBox1->TabIndex = 4;
            // 
            // textBox2
            // 
            this->textBox2->Location = System::Drawing::Point(448, 71);
            this->textBox2->Name = L"textBox2";
            this->textBox2->Size = System::Drawing::Size(100, 20);
            this->textBox2->TabIndex = 5;
            // 
            // label2
            // 
            this->label2->AutoSize = true;
            this->label2->Location = System::Drawing::Point(335, 34);
            this->label2->Name = L"label2";
            this->label2->Size = System::Drawing::Size(43, 13);
            this->label2->TabIndex = 6;
            this->label2->Text = L"liameter";
            // 
            // label3
            // 
            this->label3->AutoSize = true;
            this->label3->Location = System::Drawing::Point(338, 71);
            this->label3->Name = L"label3";
            this->label3->Size = System::Drawing::Size(36, 13);
            this->label3->TabIndex = 7;
            this->label3->Text = L"length";
            // 
            // label4
            // 
            this->label4->AutoSize = true;
            this->label4->Location = System::Drawing::Point(466, 210);
            this->label4->Name = L"label4";
            this->label4->Size = System::Drawing::Size(35, 13);
            this->label4->TabIndex = 8;
            this->label4->Text = L"label4";
            
            // 
            // Form1
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(593, 287);
            this->Controls->Add(this->label4);
            this->Controls->Add(this->label3);
            this->Controls->Add(this->label2);
            this->Controls->Add(this->textBox2);
            this->Controls->Add(this->textBox1);
            this->Controls->Add(this->button2);
            this->Controls->Add(this->label1);
            this->Controls->Add(this->button1);
            this->Name = L"Form1";
            this->Text = L"Form1";
            this->ResumeLayout(false);
            this->PerformLayout();
 
        }
#pragma endregion
 
        Int32 timeCounter; 
        USHORT** pReadData;
        ULONG nReadDataLen;
        bool stop;
        USHORT nextcircle;
        int delay;
        double consumption;
        double time;
        USHORT ar;
        
HANDLE   hNamedPipe;
 
[STAThreadAttribute]
void launch(double diameter, double length) {
    // запустить приложение
    
 
    LPCWSTR pipeName = L"\\\\.\\pipe\\demo_pipe";
    nReadDataLen = BUF_4K_LEN;
    DWORD   dwBytesRead;
    stop = false;
    hNamedPipe = CreateFile(
    pipeName,          // имя канала
    GENERIC_READ | GENERIC_WRITE,       // читаем и записываем в канал
    FILE_SHARE_READ | FILE_SHARE_WRITE, // разрешаем чтение и запись 
    NULL,                  // безопасность по умолчанию
    OPEN_EXISTING,         // открываем существующий канал
    FILE_ATTRIBUTE_NORMAL, // атрибуты по умолчанию
    NULL);
    pReadData = new USHORT *[4];
    for(int i=0;i<4;i++)
    {
        pReadData[i] = new USHORT[nReadDataLen];
        memset(pReadData[i],0,nReadDataLen*sizeof(USHORT));//
    }
    
    for (int i = 0; i < 4; i++)
        ReadFile(hNamedPipe, pReadData[i], nReadDataLen*sizeof(USHORT),&dwBytesRead, NULL);
    ar = pReadData[0][0];
    /*delay = correlation(pReadData[0], pReadData[1]);
    nextcircle = pReadData[0][delay];
    time = 1; // будет потом
    consumption = consumption2(delay, diameter, length);*/
    for(int i=0;i<4;i++)
    {
        delete pReadData[i];
    }
    while (!stop){
        pReadData = new USHORT *[4];
        for(int i=0;i<4;i++)
        {
            pReadData[i] = new USHORT[nReadDataLen];
            memset(pReadData[i],0,nReadDataLen*sizeof(USHORT));
        }
    
        for (int i = 0; i < 4; i++)
            ReadFile(hNamedPipe, pReadData[i], nReadDataLen*sizeof(USHORT),&dwBytesRead, NULL);
        ar = pReadData[0][0];
        /*if (pReadData[0][0] == nextcircle)
        {
            delay = correlation(pReadData[0], pReadData[1]);
            nextcircle = pReadData[0][delay];
            time = 1; // будет потом
            consumption = consumption + consumption2(time, diameter, length);
        }*/
    
        for(int i=0;i<4;i++)
        {
            delete pReadData[i];
        }
    }
}
int correlation(USHORT firstmassiv[], USHORT secondmassiv[])
{
    int delay;
    for (int i = 0; i < 4096; i++) //выглядит коряво, для теста пойдет
    {
        if (firstmassiv[0]/secondmassiv[i] > 0.9)
            if (firstmassiv[1]/secondmassiv[i+1] > 0.9)
                if (firstmassiv[2]/secondmassiv[i+2] > 0.9)
                    if (firstmassiv[3]/secondmassiv[i+3] > 0.9)
                        if (firstmassiv[4]/secondmassiv[i+4] > 0.9)
                            delay = i;
    }
    return delay;
}
double consumption2(double time, double diameter, double length)
{
    double consumption = PI*diameter*diameter/4/time*length;
    return consumption;
}
        
 
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
        double diameter, length;
        
        diameter = System::Double::Parse(this->textBox1->Text);
        length = System::Double::Parse(this->textBox2->Text);
 
        launch(diameter, length);
             
        timer1->Interval = 60000;
        timer1->Enabled = true;
 
             }
    private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
        label1->Text = ar.ToString();
        //label4->Text=pReadData[1][0];
        // label1->Text = consumption.toString(); - на будущее
             }
    private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
                 timer1->Stop();
                 stop = true;
             }
 
};
}
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
03.06.2019, 11:54 13
Цитата Сообщение от narsky Посмотреть сообщение
осле начала передачи данных просто зависает и ни на что не реагирует
Это легче всего проверить через отладчик: прервать выполнение всех потоков и посмотреть, кто что делает.
А зависает она скорее всего потому, что ты блокируешь поток обработки сообщений окна чтением данных из пайпа. Сообщения не обрабатываются - окно ни на что не реагирует. Продолжительные операции необходимо выполнять асинхронно. Как это сделать конкретно в Windows Forms я не знаю.
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
03.06.2019, 18:41  [ТС] 14
nonedark2008, Хорошо, а такой вопрос - пайп может некоторые данные из пайпа не читать? К примеру, если я хочу из одного приложения с помощью цикла передавать одну и ту же обновляемую переменную (которую я буду там находить) и принимать её во втором также с помощью цикла, обрабатывать и выводить в форму, при этом возможно, что второй цикл будет работать медленнее. Будут ли данные теряться в таком случае?
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
03.06.2019, 22:16 15
Цитата Сообщение от narsky Посмотреть сообщение
Будут ли данные теряться в таком случае?
У пайпа есть собственный буфер для данных. Если этот буфер заполнится, то операция записи в пайп будет заблокирована до тех пор, пока другая сторона эти данные не прочитает. Так что нет, данные теряться не будут, а скорость работы циклов будет автоматически синхронизироваться.

Если наоборот желательно, чтобы старые данные "терялись", то возможно стоит рассмотреть вариант с общей памятью, мьютексом для синхронизации доступа и ивентом для сигнализации об обновлении данных в общей памяти.
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
05.06.2019, 21:06  [ТС] 16
nonedark2008, понятно, спасибо, но все опять же сводится к тому, что обмен данными между приложениями через пайп препятствует обновлению метки в приложении-получателе. Проверял на работоспособность работу пайпа без бесконечных циклов, все работает, попытался выделить в отдельный поток обновление метки через backgroundworker и invoke - увы, проблема не исчезла. Сейчас подумываю над тем, чтобы второе приложение написать в более новой версии vs (старше, чем 2010), где можно воспользоваться библиотекой thread и с её помощью реализовать одновременную передачу данных через пайп и обновление label
Приложение-сервер:
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
#include <Windows.h>
#include "stdafx.h"
#include <iostream>
#include <string.h>
 
#pragma once
 
namespace Test {
 
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
 
    /// <summary>
    /// Summary for Form1
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
        }
 
    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }
    private: System::Windows::Forms::Button^  button1;
    protected: 
 
    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;
 
#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->button1 = (gcnew System::Windows::Forms::Button());
            this->SuspendLayout();
            // 
            // button1
            // 
            this->button1->Location = System::Drawing::Point(51, 106);
            this->button1->Name = L"button1";
            this->button1->Size = System::Drawing::Size(75, 23);
            this->button1->TabIndex = 0;
            this->button1->Text = L"button1";
            this->button1->UseVisualStyleBackColor = true;
            this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
            // 
            // Form1
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(284, 262);
            this->Controls->Add(this->button1);
            this->Name = L"Form1";
            this->Text = L"Form1";
            this->ResumeLayout(false);
 
        }
#pragma endregion
 
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
                 HANDLE hNamedPipe;
                 hNamedPipe = CreateNamedPipe(
                     L"\\\\.\\pipe\\demo_pipe",          // имя канала
                     PIPE_ACCESS_DUPLEX,        // читаем из канала и пишем в канал
                     PIPE_TYPE_MESSAGE | PIPE_WAIT,   // синхронная передача сообщений
                     1,         // максимальное количество экземпляров канала 
                     0,         // размер выходного буфера по умолчанию
                     0,         // размер входного буфера по умолчанию
                     INFINITE,  // клиент ждет связь бесконечно долго
                     NULL       // безопасность по умолчанию
                     );
                 ConnectNamedPipe(
                     hNamedPipe,    // дескриптор канала
                     NULL      // связь синхронная
                     );
                 DWORD dwBytesWritten;
                 int counter = 0;
                 while (true) {
 
                 //char buffer[6] = "ddddd";
                 //WriteFile(hNamedPipe, buffer, 6*sizeof(char), &dwBytesWritten, NULL);
                     USHORT* pReadData[2];
                     for(int i=0;i<2;i++)
                     {
                         pReadData[i] = new USHORT[4096];
                         memset(pReadData[i],0,4096*sizeof(USHORT));//
                     }
                     
                     for (int  i =0; i <2; i++)
                     {
                         for (int j = 0; j < 4096; j++)
                         {
                             pReadData[i][j] = i + j + counter;
                         }
                     }
                     counter++;
                     for (int i = 0; i < 2; i++)
                     {
                         WriteFile(hNamedPipe, pReadData[i], 4096*sizeof(USHORT), &dwBytesWritten, NULL);
                     }
                     if (counter == 10000)
                         counter = 0;
                     for(int i=0;i<2;i++)
                     {
                         delete pReadData[i];
                     }
                 }
             };          
};
}
Приложение-клиент:
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
#include <Windows.h>
#include <iostream>   // std::cout
#include <string>
 
#pragma once
 
namespace test2 {
 
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
 
    /// <summary>
    /// Summary for Form1
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
        }
 
    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }
    private: System::Windows::Forms::Label^  label1;
    private: System::Windows::Forms::Button^  button1;
    private: System::ComponentModel::BackgroundWorker^  backgroundWorker1;
    protected: 
 
    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;
 
#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->label1 = (gcnew System::Windows::Forms::Label());
            this->button1 = (gcnew System::Windows::Forms::Button());
            this->backgroundWorker1 = (gcnew System::ComponentModel::BackgroundWorker());
            this->SuspendLayout();
            // 
            // label1
            // 
            this->label1->AutoSize = true;
            this->label1->Location = System::Drawing::Point(229, 124);
            this->label1->Name = L"label1";
            this->label1->Size = System::Drawing::Size(35, 13);
            this->label1->TabIndex = 0;
            this->label1->Text = L"label1";
            // 
            // button1
            // 
            this->button1->Location = System::Drawing::Point(102, 111);
            this->button1->Name = L"button1";
            this->button1->Size = System::Drawing::Size(75, 23);
            this->button1->TabIndex = 1;
            this->button1->Text = L"button1";
            this->button1->UseVisualStyleBackColor = true;
            this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
            // 
            // backgroundWorker1
            // 
            this->backgroundWorker1->DoWork += gcnew System::ComponentModel::DoWorkEventHandler(this, &Form1::backgroundWorker1_DoWork);
            
            // 
            // Form1
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(284, 262);
            this->Controls->Add(this->button1);
            this->Controls->Add(this->label1);
            this->Name = L"Form1";
            this->Text = L"Form1";
            this->ResumeLayout(false);
            this->PerformLayout();
 
        }
#pragma endregion
    USHORT ar;
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
                 LPCWSTR pipeName = L"\\\\.\\pipe\\demo_pipe";
                 DWORD   dwBytesRead;
                 
                 HANDLE hNamedPipe;
                 hNamedPipe = CreateFile(
    pipeName,          // имя канала
    GENERIC_READ | GENERIC_WRITE,       // читаем и записываем в канал
    FILE_SHARE_READ | FILE_SHARE_WRITE, // разрешаем чтение и запись 
    NULL,                  // безопасность по умолчанию
    OPEN_EXISTING,         // открываем существующий канал
    FILE_ATTRIBUTE_NORMAL, // атрибуты по умолчанию
    NULL);
                 this->backgroundWorker1->RunWorkerAsync();
                 while (true)
                     {
                         USHORT* pReadData[2];
                 for(int i=0;i<2;i++)
    {
        pReadData[i] = new USHORT[4096];
        memset(pReadData[i],0,4096*sizeof(USHORT));//
    }
    
    for (int i = 0; i < 2; i++)
        ReadFile(hNamedPipe, pReadData[i], 4096*sizeof(USHORT),&dwBytesRead, NULL);
                 //char buffer[6];
                 //ReadFile(hNamedPipe, buffer, 6*sizeof(char),&dwBytesRead, NULL);
    //label1->Text = pReadData[1][1].ToString();
    ar = pReadData[0][10];           
    for(int i=0;i<2;i++)
                     {
                         delete pReadData[i];
                     }           
             }
             }
             private: delegate void dText_help(String ^);
 
             private: void Text_help (String ^ data)
 {
 label1->Text=data;
 }
             /*private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
    if (this->label1->InvokeRequired)
    {
        this->Invoke(new UpdateStatusDelegate(this->UpdateStatus), new object[] { status });
        return;
    }
 
    this->label1->Text = status;
}*/
             
private: System::Void backgroundWorker1_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {
         //UpdateStatus(ar.ToString());
 
             if (this->label1->InvokeRequired) this->Invoke(gcnew dText_help(this, &Form1::Text_help), ar.ToString());
 
         Sleep(10000);}
 
         
};
}
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
06.06.2019, 00:28 17
Цитата Сообщение от narsky Посмотреть сообщение
где можно воспользоваться библиотекой thread
Еще можно рассмотреть асинхронный ввод/вывод через пайпы. Ну и в Winapi, да и в Windows Forms есть свои примитивы для работы с потоками, так что можно обойтись и без std::thread.
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
06.06.2019, 09:37  [ТС] 18
nonedark2008, лол, нужно было лишь добавить
C++
1
Application::DoEvents();
в каждой итерации циклов и все заработало...
Но при этом я там же написал функцию Sleep, и теперь вот думаю, данные в таком случае не будут теряться из-за задержки, скажем в секунду? Может в каждой итерации цикла стоит запускать backgroundworker, в котором и будет
C++
1
Application::DoEvents();
вместе со sleep, чтобы работа цикла не прерывалась?
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
06.06.2019, 16:34 19
Цитата Сообщение от narsky Посмотреть сообщение
Может
Не знаю, никогда не работал с Windows Forms
0
2 / 2 / 2
Регистрация: 23.03.2016
Сообщений: 142
08.06.2019, 18:21  [ТС] 20
А как будет правильно запустить exe-файл другой программы через первую программу? В обработчик событий кнопки добавил данный код, взятый с msdn
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
STARTUPINFO si;     
   PROCESS_INFORMATION pi;
 
   // set the size of the structures
   ZeroMemory( &si, sizeof(si) );
   si.cb = sizeof(si);
   ZeroMemory( &pi, sizeof(pi) );
   
 
  // start the program up
  CreateProcess( NULL,   // the path
    L"C:\\Users\\User\\Desktop\\Debug\\Program.exe",        // Command line
    NULL,           // Process handle not inheritable
    NULL,           // Thread handle not inheritable
    FALSE,          // Set handle inheritance to FALSE
    0,              // No creation flags
    NULL,           // Use parent environment block
    NULL,           // Use parent starting directory 
    &si,            // Pointer to STARTUPINFO structure
    &pi             // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
    );
    WaitForSingleObject( pi.hProcess, INFINITE );// Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
но увы, не работает, выдавая ошибку ниже. С чем это может быть связано, как решить эту проблему, и ничего нет в том, что я пытаюсь запустить debug файл другого проекта? (вручную этот exe-файл запускается и работает без проблем)
Миниатюры
Одновременная передача данных в виде двух массивов через буфер обмена  
0
08.06.2019, 18:21
cpp_developer
Эксперт
20123 / 5690 / 417
Регистрация: 09.04.2010
Сообщений: 12,546
Блог
08.06.2019, 18:21
Помогаю со студенческими работами здесь

Передача данных в виде структуры через ClientSocket
Проблема заключается в том что нужно передать структурный тип данных struct zakaz { ...

Сохранение кнопок через буфер обмена
Помогите разобраться пожалуйста суть задачи такова,по нажатию на форму,создаются кнопки (button),в...

Копирование файла через буфер обмена
С текстом все просто: https://www.cyberforum.ru/vb-net/thread364372.html Как быть с файлом?

Одновременная передача и прием данных
Здравствуйте! При попытки передать и получить данные одновременно, возникает проблема, т.е. при...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Блоги программистов
Обновление сайта www.historian.b­y
Reglage 05.01.2025
Обещал подвести итоги 2024 года для сайта. Однако начну с того, что изменилось за неделю. Добавил краткий урок по последовательности действий при анализе вредоносных файлов и значительно улучшил урок. . .
Как использовать GraphQL в C# с HotChocolate
Programming 05.01.2025
GraphQL — это современный подход к разработке API, который позволяет клиентам запрашивать только те данные, которые им необходимы. Это делает взаимодействие с API более гибким и эффективным по. . .
Модель полного двоичного суматора с помощью логических операций (python)
AlexSky-coder 04.01.2025
def binSum(x:list, y:list): s=^y] p=x and y for i in range(1,len(x)): s. append((x^y)^p) p=(x and y)or(p and (x or y)) return s x=list() y=list()
Это мы не проходили, это нам не задавали...(аси­­хронный счётчик с управляющим сигналом задержки).
Hrethgir 04.01.2025
Асинхронный счётчик на сумматорах (шестиразрядный по числу диодов на плате, но наверное разрядов будет больше - восемь или шестнадцать, а диоды на старшие), так как триггеры прошли тестирование и. . .
Руководство по созданию бота для Телеграм на Python
IT_Exp 04.01.2025
Боты для Телеграм представляют собой автоматизированные программы, которые выполняют различные задачи, взаимодействуя с пользователями через интерфейс мессенджера. В данной статье мы рассмотрим,. . .
Применение компонентов PrimeVue в Vue.js 3 на TypeScript
BasicMan 04.01.2025
Введение в PrimeVue и настройка окружения PrimeVue представляет собой мощную библиотеку компонентов пользовательского интерфейса для Vue. js 3, которая предоставляет разработчикам богатый набор. . .
Как стать Senior developer
cpp_developer 04.01.2025
В современной индустрии разработки программного обеспечения позиция Senior Developer представляет собой не просто следующую ступень карьерной лестницы, а качественно новый уровень профессионального. . .
Что известно о дате выхода Windows 12 и чего от нее ждать
IT_Exp 04.01.2025
В мире технологий постоянно происходят изменения, и операционные системы не являются исключением. Windows 11, выпущенная в октябре 2021 года, принесла множество инноваций и улучшений, но. . .
Что новенького в .NET Core 9
Programming 04.01.2025
Обзор ключевых изменений в . NET Core 9 Платформа . NET Core продолжает активно развиваться, и версия 9 представляет собой значительный шаг вперед в эволюции этой технологии. Новый релиз. . .
Инструкция по установке python3.13.1 в Debian 12
AlexSky-coder 03.01.2025
sudo apt update sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget. . .
Затестил триггеры. архив проекта прилагаю с GOA файлами в настройках архиватора проектов.
Hrethgir 03.01.2025
В этот раз нет закольцованности, потому что от неё только глюки, как я понял, логика не вырезанная. Триггеры очень быстрые если верить измерениям с помощью анализатора от Gowin. Есть ещё регистры,. . .
Python в помощь DevOps
IT_Exp 03.01.2025
Причины использования Python в работе DevOps Python стал неотъемлемой частью мира DevOps, и это не случайно. Этот язык программирования обладает множеством преимуществ, которые делают его. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru