Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как совместить чтение Mailslot и WaitForMultipleObjects? / 20 сообщений из 20, страница 1 из 1
25.01.2017, 20:54
    #39391606
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Грубо, есть функция DeviceReceiveThread.
Выполняется в своем потоке, ожидающем сигнала о том что есть "входящий телефонный вызов".
На всякий случай приведу ее оригинал (из MS SDK) целиком под спойлером:
Код: plaintext
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.
//+---------------------------------------------------------------------------
//
//  function:   DeviceReceiveThread
//
//  Synopsis:   Thread to watch for an incoming fax transmission
//
//  Arguments:  [pdwDeviceId] - pointer to the virtual fax device identifier
//
//  Returns:    DWORD
//
//----------------------------------------------------------------------------
DWORD WINAPI DeviceReceiveThread(LPDWORD pdwDeviceId)       
{
        // hChangeNotification is a handle to a notification change in a directory
        HANDLE         hChangeNotification;
        // hWaitObjects are the handles to the wait objects
        HANDLE         hWaitObjects[2];
        // dwDeviceId is the virtual fax device identifier
        DWORD          dwDeviceId;
        // pLineMessage is a pointer to LINEMESSAGE structure to signal an incoming fax transmission to the fax service
        LPLINEMESSAGE  pLineMessage;

        //WriteDebugString(L"---SampleFSP: DeviceReceiveThread Enter---\r\n");

        // Copy the virtual fax device identifier
        dwDeviceId = *pdwDeviceId;
        MemFreeMacro(pdwDeviceId);
		WriteDebugString(L"---SampleFSP: DeviceReceiveThread (Device=%x) Enter---\r\n", dwDeviceId);

        // Create the change notification handle
        hChangeNotification = FindFirstChangeNotification(g_pDeviceInfo[dwDeviceId]->Directory,
                        FALSE, 
                        FILE_NOTIFY_CHANGE_ATTRIBUTES);
        if (hChangeNotification == INVALID_HANDLE_VALUE) {
                goto Exit;
        }

        // Wait for access to this virtual fax device
        EnterCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

        // Set hWaitObjects
        hWaitObjects[0] = g_pDeviceInfo[dwDeviceId]->ExitEvent;
        hWaitObjects[1] = hChangeNotification;

        // Release access to this virtual fax device
        LeaveCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

        while (TRUE) {
                // Wait for the exit event or notification change to be signaled
                if ( WaitForMultipleObjects(2,
                                        hWaitObjects,
                                        FALSE,
                                        INFINITE) == WAIT_OBJECT_0) {
                        break;
                }

                // Wait for access to this virtual fax device
                EnterCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

                if (g_pDeviceInfo[dwDeviceId]->Status == DEVICE_IDLE) {
                        // Allocate a block of memory for the completion packet
                        pLineMessage = (LPLINEMESSAGE) LocalAlloc(LPTR, sizeof(LINEMESSAGE));
                        if (pLineMessage != NULL) {
                                // Initialize the completion packet
                                // Set the completion packet's handle to the virtual fax device
                                pLineMessage->hDevice = dwDeviceId + NEWFSP_DEVICE_ID_PREFIX;
                                // Set the completion packet's virtual fax device message
                                pLineMessage->dwMessageID = 0;
                                // Set the completion packet's instance data
                                pLineMessage->dwCallbackInstance = 0;
                                // Set the completion packet's first parameter
                                pLineMessage->dwParam1 = LINEDEVSTATE_RINGING;
                                // Set the completion packet's second parameter
                                pLineMessage->dwParam2 = 0;
                                // Set the completion packet's third parameter
                                pLineMessage->dwParam3 = 0;

								WriteDebugString(L"---SampleFSP: DeviceReceiveThread (Device=%x) Signaling Fax Service...---\r\n", dwDeviceId);

                                // Post the completion packet
                                PostQueuedCompletionStatus(g_CompletionPort, 
                                                sizeof(LINEMESSAGE),
                                                g_CompletionKey,
                                                (LPOVERLAPPED) pLineMessage);
                        }
                }

                // Release access to this virtual fax device
                LeaveCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

                // Find the next notification change
                FindNextChangeNotification(hChangeNotification);
        }

Exit:
        if (hChangeNotification != INVALID_HANDLE_VALUE) {
                // Close the handle to the change notification
                FindCloseChangeNotification(hChangeNotification);
        }

        // Close the handle to the exit event
        CloseHandle(hWaitObjects[0]);

        //WriteDebugString(L"---SampleFSP: DeviceReceiveThread Exit---\r\n");
		WriteDebugString(L"---SampleFSP: DeviceReceiveThread (Device=%x) Exit---\r\n", dwDeviceId);

        return 0;
}


Смысл такой.
Бесконечно ждет через WaitForMultipleObjects одного из 2-х "сигналов":
(1) Сигнал на выход из функции (реализован внутри библиотеки)
Т.е. когда пользователь решил не использовать "девайс" для приема вызовов, по этому сигналу функция самозавершается.
Код: plaintext
1.
hWaitObjects[0] = g_pDeviceInfo[dwDeviceId]->ExitEvent;


Это меня устраивает.
(2) Сигнал о том, что есть входящий вызов, на который надо реагировать.
В тестовой SDK-библиотеке это реализовано так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
        // Create the change notification handle
        hChangeNotification = FindFirstChangeNotification(g_pDeviceInfo[dwDeviceId]->Directory,
                        FALSE, 
                        FILE_NOTIFY_CHANGE_ATTRIBUTES);
        if (hChangeNotification == INVALID_HANDLE_VALUE) {
                goto Exit;
        }
        hWaitObjects[1] = hChangeNotification;


Т.е. этот объект следит за изменением атрибутов файлов в заданной папке g_pDeviceInfo[dwDeviceId]->Directory через FindFirstChangeNotification.
и как только я поменял какой-то атрибут у какого-то файла, это будет "звоночек в функцию".
Это сделано для теста.

Меня устраивает (1) и я не хочу это менять но ясен пень не устраивает (2).
(2) я хочу реализовать так.
читать MailSlot в этой ф-ции, как-только есть сообщение это означает "звоночек" и WaitForMultipleObjects выходит.
Т.е. мне надо стукнуть в DeviceReceiveThread из другого приложения (при этом желат. получить ответ, но это уже другой вопрос).

Как мне увязать WaitForMultipleObjects и MailSlot?
MailSlot обычно читается циклом, (либо бесконечное ожидание).

Т.е. мне нужно внутри ф-ции сделать hWaitObjects[1] который бы стучал в WaitForMultipleObjects "в MailSlot есть сообщение".
Я не могу одновременно бесконечно ждать сообщение MailSlot (через ReadFile) и бесконечно ждать ->ExitEvent (через WaitForMultiple(Single)Objects).
Если я сделаю цикл с небесконечными ожиданиями, то не работает принцип "как только так сразу" для любого из событий, и не уверен что это есть хорошо.

Как извернуться?
...
Рейтинг: 0 / 0
25.01.2017, 21:30
    #39391632
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77Как извернуться?
изворачиваться не надо, ибо MailSlot поддерживает Overlapped I/O

и WaitForMultipleObjects вполне может ждать заодно и чтения из мейлслота.
...
Рейтинг: 0 / 0
25.01.2017, 21:58
    #39391644
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Изопропил,

Пока каша.

Вот в этом примере:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365785(v=vs.85).aspx
есть

&ov в ReadFile(hSlot,

и есть

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
    OVERLAPPED ov;

    hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
    if( NULL == hEvent )
        return FALSE;
    ov.Offset = 0;
    ov.OffsetHigh = 0;
    ov.hEvent = hEvent;



мне это пока ни о чем не говорит.

В C я обычно читаю его циклом (таймаут задан в CreateMailSlot, могу в этом цикле делать еще что-то)
Код: plaintext
1.
2.
		while (TRUE) {
		  if (ReadFile(hMailSlotHandle, buff, 1000, &NumberOfBytesRead, NULL) != 0) {



В .Net я многопоточность так толком и не освоил (а в VB6 ее в рабочем виде и не было никогда),
поэтому роскошь сидеть и ждать позволить не могу
в CreateMailSlot таймаут =0
и читаем таймером скажем 300мс нет ли чего но опять же без последнего параметра
Код: vbnet
1.
If ReadFile(hMailSlotHandle, sBuffer, lBufferSize, 0, IntPtr.Zero)



Т.е. я не догоняю как сделать
и WaitForMultipleObjects вполне может ждать заодно и чтения из мейлслота.
мне даже не само чтение нужно, а "сигнал",

Мне нужен аналог вот этого:
Код: plaintext
1.
2.
hChangeNotification = FindFirstChangeNotification
hWaitObjects[1] = hChangeNotification



Хоть пример кода бы какой что-ли.
...
Рейтинг: 0 / 0
25.01.2017, 22:13
    #39391651
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77В .Net я многопоточность так толком и не освоил (а в VB6 ее в рабочем виде и не было никогда),
поэтому роскошь сидеть и ждать позволить не могу

overlapped для того и нужен, чтоб избежать многопоточности

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

придётся накидать пример - чуть позже
...
Рейтинг: 0 / 0
25.01.2017, 23:18
    #39391667
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Изопропил,

Я вот тут погуглил, нашел вот это
WaitForSingleObject and mailslot IPC
Там идея интересная:
авторYes you can. You will need to create a named event using CreateEvent in your server and then use OpenEvent in the client to get a handle to it.

So, in the server:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
// create an auto-reset event
m_hEvent = CreateEvent(NULL, FALSE, FALSE, _T("SomeUniqueName"));

// ... when you have written a mailslot message ...
SetEvent(m_hEvent);

// on shut down
CloseHandle(m_hEvent);


And in the client:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
// get a handle to the server's event
m_hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("SomeUniqueName"));

// main loop
while (/* not time to exit */)
{
    // wait for signal
    WaitForSingleObject(m_hEvent, INFINITE);

    // ... read from mailslot ....
}



Для "стукануть" похоже подойдет даже без самого mailslot.
Идея, что приложение ведающее телефонией получив Incoming Call должно стукануть в девайс через DeviceReceiveThread в FSP, а оттуда уже все запускается.
При этом DeviceReceiveThread может отсутствовать (устройство не принимает входящие вызовы), в случае если приемник-MailSlot, тогда он тоже отсутствует и отправитель получит ошибку сразу.
Но может и присутствовать (устройство принимает входящие вызовы) но при этом не иметь статус
Код: plaintext
1.
if (g_pDeviceInfo[dwDeviceId]->Status == DEVICE_IDLE) {


(т.е. устройстро уже занято обработкой другого вх. или исх. вызова).
Поэтому устройство должно по любому дать ответ, чтобы если оно "занято делом", перейти к опросу следующего.
Нет свободного, телефонное приложение футболит вызов со статусом BUSY.
Но это уже логика,
счас задача просто "стукануть", чтоб инициализировать работу FSP при входящем вызове (с исходящими более менее логику взаимодействия понял).
...
Рейтинг: 0 / 0
26.01.2017, 00:09
    #39391678
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77,

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

Код: plaintext
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.
#include "stdafx.h"

wchar_t const * slotName = L"\\\\.\\mailslot\\mstest";
int const bufSize = 1024;
BOOL WINAPI consoleHandler(DWORD ctrlType) {
	if (ctrlType == CTRL_C_EVENT) {
		HANDLE hFile = CreateFile(slotName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		DWORD sz = 0;
		int rc = WriteFile(hFile, "MSG", 3, &sz, 0);
		CloseHandle(hFile);
		return TRUE;
	}
	return FALSE;
}
int main()
{
	int rc;
	HANDLE hSlot = CreateMailslot(slotName, bufSize, MAILSLOT_WAIT_FOREVER, NULL);
	HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	rc = SetConsoleCtrlHandler(consoleHandler, TRUE);
	HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
	LARGE_INTEGER dueTime;
	dueTime.QuadPart = -20000000LL;
	rc = SetWaitableTimer(hTimer, &dueTime, 0, NULL, NULL, 0);
	char buf[bufSize + 1];
	OVERLAPPED ov = {};
	ov.hEvent = hEvent;
	rc = ReadFile(hSlot, buf, bufSize, 0, &ov);

	do {
		HANDLE events[2] = { hEvent,hTimer };
		rc = WaitForMultipleObjects(2, events, FALSE, INFINITE);
		if (rc == WAIT_FAILED) break;
		DWORD sz = 0;
		rc = GetOverlappedResult(hSlot, &ov, &sz, FALSE);
		if (rc) {
			buf[sz] = 0;
			printf("Message: %s\n", buf);
			ov = {};
			ov.hEvent = hEvent;
			rc = ReadFile(hSlot, buf, bufSize, 0, &ov);
			if (!rc && GetLastError() != ERROR_IO_PENDING) {
				break;
			}
		}
		else if (GetLastError() != ERROR_IO_INCOMPLETE) {
			break;
		}
		rc = WaitForSingleObject(hTimer, 0);
		if (rc==WAIT_OBJECT_0 ) {
			rc = SetWaitableTimer(hTimer, &dueTime, 0, NULL, NULL, 0);
			printf("Timer\n");
		}
		else if (rc != WAIT_TIMEOUT) {
			break;
		}
	} while (1);

	printf("Error: %i\n", GetLastError());

	return 0;
}
...
Рейтинг: 0 / 0
26.01.2017, 01:32
    #39391705
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Изопропил,

Я тут пока с Event тест их 2-х VB сделал, как в примере что накопал, хотя в примере перепутано немного.

Т.е. приемник создает Event (вместо mailslot) и ждет когда в него просигналят:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
  Private Sub ButtonStartEvent_Click(sender As Object, e As EventArgs) Handles ButtonStartEvent.Click
    ' create an auto-reset event
    Dim SA As SECURITY_ATTRIBUTES
    m_hEvent = CreateEvent(SA, False, False, "SomeUniqueName")
    ' main loop
    Do
      ' wait for signal
      WaitForSingleObject(m_hEvent, INFINITE)
      Debug.Print("Signal")
    Loop
    '!!! CloseHandle не забыть при выходе!!!
  End Sub



А передатчик сигналит в этот Event вот так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
  Private Sub ButtonSendSignal_Click(sender As Object, e As EventArgs) Handles ButtonSendSignal.Click
    ' get a handle to the server's event
    m_hEvent = OpenEvent(EVENT_MODIFY_STATE, False, "SomeUniqueName") 'SYNCHRONIZE Or 
    ' ???... when you have written a mailslot message ...
    If m_hEvent <> IntPtr.Zero Then
      SetEvent(m_hEvent)
      CloseHandle(m_hEvent)
    End If
  End Sub



Все работает. Отличие от MailSlot в том что Event не передает "сообщение".
Возможно Event достаточно если просто "стукануть" без передачи параметров.
SA кстати в Event можно такой же запихивать как в MailSlot? (это когда сервис с не-сервисом общается и т.п. чтоб все всех видели, есть у меня эта ф-ция).
=====
Если все-таки нужно сообщение, можно конечно пихнуть в DeviceReceiveThread Event+MailSlot (по сигналу Event читаем MailSlot),
но не перебор ли. Поэтому попытаюсь осознать твой код.
Я так понял, таймер там для "второго объекта" кот. в моем случае ->ExitEvent ?
...
Рейтинг: 0 / 0
26.01.2017, 03:48
    #39391715
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77 SA кстати в Event можно такой же запихивать как в MailSlot? (это когда сервис с не-сервисом общается и т.п. чтоб все всех видели, есть у меня эта ф-ция).
SA да, такой же. Но для Event этого недостаточно. Надо еще Global\ к имени приписывать: " Global\\ SomeUniqueName".
Ну, с Event у меня все прокатило.

Код: plaintext
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.
       std::wstringstream to_buffer;
        HANDLE hEventHandle;
        std::wstring strEventName;

        // Create the event handle
        to_buffer << L"Global\\EventMyFSPWaitLine" << dwDeviceId;
        strEventName = to_buffer.str();
        to_buffer.str(L"");
        hEventHandle = MakeEvent(&strEventName[0]);
        if (hEventHandle == NULL) {
          // Event failed to be created
          goto Exit;
        }


        // Wait for access to this virtual fax device
        EnterCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

        // Set hWaitObjects
        hWaitObjects[0] = g_pDeviceInfo[dwDeviceId]->ExitEvent;
        hWaitObjects[1] = hEventHandle;
       //hWaitObjects[1] = hChangeNotification;

        // Release access to this virtual fax device
        LeaveCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

        while (TRUE) {
                // Wait for the exit event or notification change to be signaled
                if ( WaitForMultipleObjects(2,
                                        hWaitObjects,
                                        FALSE,
                                        INFINITE) == WAIT_OBJECT_0) {
                        break;
                }

                // Wait for access to this virtual fax device
                EnterCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

                if (g_pDeviceInfo[dwDeviceId]->Status == DEVICE_IDLE) {
...



Блин, как в вашем C (13-я студия) настроить редактор кода, чтобы он {TAB}-ом отступы не добавлял.
Просто открываешь приличный код (где отступы забиты пробелами),
дописываешь свой,
а потом весь код прыгает,
хотя бы когда его сюда копируешь.
И как исправить, если уже табов поналяпано.
Я задолбался ручками табы на пробелы менять
...
Рейтинг: 0 / 0
26.01.2017, 03:56
    #39391716
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
А вроде нашел:
Сервис-> Параметры-> Текстовый редактор -> C/C++ ->Табуляция
=Вставлять пробелы
...
Рейтинг: 0 / 0
26.01.2017, 07:38
    #39391743
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Изопропил,

спасибо за код.

Поэкспериментировал в .Net, возникло понимание
Вроде фурычит как хотелось.
Код: vbnet
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.
 Private Sub ButtonStartMailSlotEvent_Click(sender As Object, e As EventArgs) Handles ButtonStartMailSlotEvent.Click
    MakeMailSlot("\\.\mailslot\mstest", True, True)
    Dim SA As SECURITY_ATTRIBUTES
    Dim hEvent As IntPtr = CreateEvent(SA, False, False, vbNullString) 'autoreset,non-signaled state
    Dim ov As OVERLAPPED
    ov.hEvent = hEvent
    Dim lBufferSize As Integer = 260 ' arbitrary - can be set higher/lower if desired
    Dim sBuffer(lBufferSize - 1) As Byte
    Dim lBytesRead As Integer 'сколько байт прочитали -чтоб обрезать буфер
    Dim rc As Integer
    rc = ReadFileOv(hMailSlotHandle, sBuffer, lBufferSize, 0, ov)
    Do
      ' wait for signal
      WaitForSingleObject(hEvent, INFINITE)
      If GetOverlappedResult(hMailSlotHandle, ov, lBytesRead, False) = False Then
        If Err.LastDllError = ERROR_INSUFFICIENT_BUFFER Then
          GetMailslotInfo(hMailSlotHandle, 0, lBufferSize, 0, 0) 'получаем точный размер буфера, если не хватило
          ReDim sBuffer(lBufferSize - 1)
          'читаем повторно с точным размером буфера
          If ReadFile(hMailSlotHandle, sBuffer, lBufferSize, lBytesRead, IntPtr.Zero) = False Then
            Exit Do 'хз-не должно такого быть
          End If
        Else
          Exit Do 'любая другая ошибка, например при обращении к несуществующему MailSlot
        End If
      Else 'в случае успеха с первого раза буфер надо обрезать
        ReDim Preserve sBuffer(lBytesRead - 1)
      End If
      Using mstream As New IO.MemoryStream(sBuffer)
        Using reader As New IO.StreamReader(mstream, System.Text.Encoding.Default, True)
          Debug.Print("'" & reader.ReadToEnd() & "'")
        End Using
      End Using
      'переинициалиация
      ov.Internal = IntPtr.Zero : ov.InternalHigh = IntPtr.Zero : ov.Offset = 0 : ov.OffsetHigh = 0 : ov.hEvent = hEvent
      lBufferSize = 260
      ReDim sBuffer(lBufferSize - 1)
      rc = ReadFileOv(hMailSlotHandle, sBuffer, lBufferSize, 0, ov)
    Loop

    '------
    CloseMailSlot()
  End Sub


Там по хорошему ERROR_INSUFFICIENT_BUFFER проверять надо, и если что перечитывать синхронно, получив точный lBufferSize через GetMailslotInfo. В VB люблю аккуратность.
Но в C этого все одно делать не буду,
Redim не осилю и т.п.
ставлю буфер=1000 с запасом, и проверками особо не балуюсь.
Все равно в mailslot мое же приложение и кладет, и больше 1000 точно не будет.
...
Рейтинг: 0 / 0
26.01.2017, 07:40
    #39391744
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77,

в студии(в "нашем" С) есть комбинация клавиш для форматирования исходников

Cntrl-K Cntrl-D
Cntrl-K Cntrl-F

и много других полезных комбинаций https://msdn.microsoft.com/ru-ru/library/da5kh0wa.aspx
...
Рейтинг: 0 / 0
26.01.2017, 07:45
    #39391746
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77Там по хорошему ERROR_INSUFFICIENT_BUFFER проверять надо
опустил в полном сознании, ибо задал макс размер в CreateMailSlot

если не задать - будут лёгкие проблемы , ибо при запуске асинхронного чтения размер сообщения ещё не известен,а если прилелетело ERROR_INSUFFICIENT_BUFFER - нужно синхронно прочитать это сообщение
...
Рейтинг: 0 / 0
26.01.2017, 08:17
    #39391755
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77Надо еще Global\ к имени приписывать
с этим поаккурантее и в полном сознании
https://msdn.microsoft.com/en-us/library/windows/desktop/aa382954(v=vs.85).aspx
...
Рейтинг: 0 / 0
26.01.2017, 16:43
    #39392290
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
ИзопропилДмитрий77Там по хорошему ERROR_INSUFFICIENT_BUFFER проверять надо
опустил в полном сознании, ибо задал макс размер в CreateMailSlot

если не задать - будут лёгкие проблемы , ибо при запуске асинхронного чтения размер сообщения ещё не известен,а если прилелетело ERROR_INSUFFICIENT_BUFFER - нужно синхронно прочитать это сообщение
Я не задаю макс размер в CreateMailSlot, но в C-кодах делаю без проверки ERROR_INSUFFICIENT_BUFFER, полагаясь на то что отсылаемое(моей же программой) сообщение не может быть длиннее 1000, которую задаю.
Но если все таки ERROR_INSUFFICIENT_BUFFER придет, то проблемы будут большие, след. сообщение уже не прочтешь.

ИзопропилДмитрий77Надо еще Global\ к имени приписывать
с этим поаккурантее и в полном сознании
https://msdn.microsoft.com/en-us/library/windows/desktop/aa382954(v=vs.85).aspx
А чем я рискую? Я надеюсь оно по сети не будет стучать на соседний компьютер или по RDP если там такое же приложение запущено. Ну, для Windows Store такие приложения не пишутся. Скорее Windows Store сдохнет, чем MS разрешит для него писать через нормальные классические API.
FSP -всегда сервис (и уже сразу во время тестов, это dll, запускаемая MS службой Fax), второе приложение (телефонная начинка) - потом видимо будет отдельным сервисом, или вообще запускаться из-под dll, но в процессе тестов и изысканий - естественно не service, поэтому по другому никак.
С mailslot никакого global не надо,
думаю ограничусь mailslot, чтоб не разводить зоопарк.
...
Рейтинг: 0 / 0
26.01.2017, 16:53
    #39392296
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77Я не задаю макс размер в CreateMailSlot, но в C-кодах делаю без проверки ERROR_INSUFFICIENT_BUFFER, полагаясь на то что отсылаемое(моей же программой) сообщение не может быть длиннее 1000, которую задаю.
Многовато, может не дойти
https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa365147(v=vs.85).aspx If CreateFile specifies a domain or uses the asterisk format to specify the system's primary domain, the application cannot write more than 424 bytes at a time to the mailslot. If the application attempts to do so, the WriteFile function fails and GetLastError returns ERROR_BAD_NETPATH.
Тут тоже упоминается 424 https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa365130(v=vs.85).aspx
...
Рейтинг: 0 / 0
26.01.2017, 17:04
    #39392307
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77SA да, такой же. Но для Event этого недостаточно. Надо еще Global\ к имени приписывать: " Global\\ SomeUniqueName".
Ну, с Event у меня все прокатило.
Не везде прокатывает, там еще права надо давать, чтобы из других сессий до него добраться. 18479811
...
Рейтинг: 0 / 0
26.01.2017, 18:50
    #39392410
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Dima TМноговато, может не дойти
Тут тоже упоминается 424
Ну, таких длинных не посылаем. Буфер в 1000 это перестраховка из-за нежелания обрабатывать ERROR_INSUFFICIENT_BUFFER в C.
Тогда вообще можно не париться и не переживать, раз длинное все одно не дойдет.
В VB я всегда делаю 260, при этом с обработкой ERROR_INSUFFICIENT_BUFFER.
Dima TДмитрий77SA да, такой же. Но для Event этого недостаточно. Надо еще Global\ к имени приписывать: " Global\\ SomeUniqueName".
Ну, с Event у меня все прокатило.
Не везде прокатывает, там еще права надо давать, чтобы из других сессий до него добраться. 18479811
Ну, это я в курсе, об этом я как раз в первую очередь подумал, до того как про Global доперло.
Функцию ниже писал для mailslot но она одинаково подходит и для Event.
Код: plaintext
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.
BOOL CreateMailslotSecurityFullAccess(PSECURITY_ATTRIBUTES *ppSa)
{
  //http://www.getcodesamples.com/src/C2B025C1/8BBD4E37
  BOOL fSucceeded = TRUE;
  DWORD dwError = ERROR_SUCCESS;

  PSECURITY_DESCRIPTOR pSd = NULL;
  PSECURITY_ATTRIBUTES pSa = NULL;

  // Define the SDDL for the security descriptor.
  // DACL + OBJECT_INHERIT_ACE/CONTAINER_INHERIT_ACE + GENERIC_ALL (полный доступ) + SECURITY_WORLD_RID (группа "EveryOne")
  LPTSTR szSDDL = TEXT("D:(A;OICI;GA;;;WD)");

  if (!ConvertStringSecurityDescriptorToSecurityDescriptor(szSDDL,
	SDDL_REVISION_1, &pSd, NULL))
  {
	fSucceeded = FALSE;
	dwError = GetLastError();
	goto Cleanup;
  }

  // Allocate the memory of SECURITY_ATTRIBUTES.
  pSa = (PSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(*pSa));
  if (pSa == NULL)
  {
	fSucceeded = FALSE;
	dwError = GetLastError();
	goto Cleanup;
  }

  pSa->nLength = sizeof(*pSa);
  pSa->lpSecurityDescriptor = pSd;
  pSa->bInheritHandle = FALSE;

  *ppSa = pSa;

Cleanup:
  // Clean up the allocated resources if something is wrong.
  if (!fSucceeded)
  {
	if (pSd)
	{
	  LocalFree(pSd);
	  pSd = NULL;
	}
	if (pSa)
	{
	  LocalFree(pSa);
	  pSa = NULL;
	}
	SetLastError(dwError);
  }

  return fSucceeded;
}



Короче сделал я с Mailslot, все получилось, примерно так:

Код: plaintext
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.
        std::wstringstream to_buffer;
        HANDLE hEventHandle;
        HANDLE hMailSlotHandle;
        std::wstring strMailSlotName;
        OVERLAPPED ov;
...

        // Create the event handle
        hEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (hEventHandle == NULL) {
          // Event failed to be created
          goto Exit;
        }
        // Wait for access to this virtual fax device
        EnterCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

        // Set hWaitObjects
        hWaitObjects[0] = g_pDeviceInfo[dwDeviceId]->ExitEvent;
        hWaitObjects[1] = hEventHandle;

        // Release access to this virtual fax device
        LeaveCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

        // Create the Mailslot
        to_buffer << L"\\\\.\\mailslot\\MailSlotMyFSPWaitLine" << dwDeviceId;
        strMailSlotName = to_buffer.str();
        to_buffer.str(L"");
        hMailSlotHandle = MakeMailSlot(&strMailSlotName[0], MAILSLOT_WAIT_FOREVER);
        if (hMailSlotHandle == INVALID_HANDLE_VALUE) {
          // The mailslot failed to be created
          goto Exit;
        }
        wchar_t buff[1000];
        ov = {};
        ov.hEvent = hEventHandle;
        ReadFile(hMailSlotHandle, buff, 1000, 0, &ov);
        while (TRUE) {
                // Wait for the exit event or notification change to be signaled
                if ( WaitForMultipleObjects(2,
                                        hWaitObjects,
                                        FALSE,
                                        INFINITE) == WAIT_OBJECT_0) {
                        break;
                }

                DWORD NumberOfBytesRead = 0;
                if (GetOverlappedResult(hMailSlotHandle, &ov, &NumberOfBytesRead, FALSE)) {
                  std::wstring str_message(buff);
                  WriteDebugString(L"   Message '%s' received.\r\n", str_message.c_str());
                  ov = {};
                  ov.hEvent = hEventHandle;
                  ReadFile(hMailSlotHandle, buff, 1000, 0, &ov);
                }
                
                // Wait for access to this virtual fax device
                EnterCriticalSection(&g_pDeviceInfo[dwDeviceId]->cs);

                if (g_pDeviceInfo[dwDeviceId]->Status == DEVICE_IDLE) {
...



Типа лог:
Код: plaintext
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.
01.26.2017@18:33:42.070:
---SampleFSP: DeviceReceiveThread (Device=0) Enter---
01.26.2017@18:33:42.070:
   Mailslot \\.\mailslot\MailSlotMyFSPWaitLine0 created successfully.
01.26.2017@18:34:30.979:
---SampleFSP: fnFaxLineCallback Enter---
01.26.2017@18:34:30.979:
   Device=0;Receive=0;Send=1
01.26.2017@18:34:30.979:
---SampleFSP: fnFaxLineCallback Exit---
01.26.2017@18:34:30.979:
   Mailslot \\.\mailslot\MailSlotMyFSPWaitLine0 deleted.
01.26.2017@18:34:30.979:
---SampleFSP: DeviceReceiveThread (Device=0) Exit---
01.26.2017@18:34:35.195:
---SampleFSP: fnFaxLineCallback Enter---
01.26.2017@18:34:35.195:
   Device=0;Receive=1;Send=1
01.26.2017@18:34:35.195:
---SampleFSP: fnFaxLineCallback Exit---
01.26.2017@18:34:35.195:
---SampleFSP: DeviceReceiveThread (Device=0) Enter---
01.26.2017@18:34:35.195:
   Mailslot \\.\mailslot\MailSlotMyFSPWaitLine0 created successfully.
01.26.2017@18:35:40.856:
   Message 'Incoming Call' received.
01.26.2017@18:35:40.856:
---SampleFSP: DeviceReceiveThread (Device=0) Signaling Fax Service...---
01.26.2017@18:35:40.856:
---SampleFSP: FaxDevStartJob (Device=0) Enter---
01.26.2017@18:35:40.856:
---SampleFSP: FaxDevStartJob (Device=0) Exit---
01.26.2017@18:35:40.856:
---SampleFSP: FaxDevReceive Enter---
01.26.2017@18:35:40.856:
   CallHandle                 : 0x00000000
...

...
Рейтинг: 0 / 0
26.01.2017, 19:05
    #39392427
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77Буфер в 1000 это перестраховка из-за нежелания обрабатывать ERROR_INSUFFICIENT_BUFFER в C.
Тогда вообще можно не париться и не переживать, раз длинное все одно не дойдет.
В VB я всегда делаю 260, при этом с обработкой ERROR_INSUFFICIENT_BUFFER.
хозяин-барин, но это извращение.
...
Рейтинг: 0 / 0
11.04.2017, 04:20
    #39436226
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Изопропил,
ИзопропилДмитрий77,

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

Код: plaintext
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.
#include "stdafx.h"

wchar_t const * slotName = L"\\\\.\\mailslot\\mstest";
int const bufSize = 1024;
BOOL WINAPI consoleHandler(DWORD ctrlType) {
	if (ctrlType == CTRL_C_EVENT) {
		HANDLE hFile = CreateFile(slotName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		DWORD sz = 0;
		int rc = WriteFile(hFile, "MSG", 3, &sz, 0);
		CloseHandle(hFile);
		return TRUE;
	}
	return FALSE;
}
int main()
{
	int rc;
	HANDLE hSlot = CreateMailslot(slotName, bufSize, MAILSLOT_WAIT_FOREVER, NULL);
	HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	rc = SetConsoleCtrlHandler(consoleHandler, TRUE);
	HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
	LARGE_INTEGER dueTime;
	dueTime.QuadPart = -20000000LL;
	rc = SetWaitableTimer(hTimer, &dueTime, 0, NULL, NULL, 0);
	char buf[bufSize + 1];
	OVERLAPPED ov = {};
	ov.hEvent = hEvent;
	rc = ReadFile(hSlot, buf, bufSize, 0, &ov);

	do {
		HANDLE events[2] = { hEvent,hTimer };
		rc = WaitForMultipleObjects(2, events, FALSE, INFINITE);
		if (rc == WAIT_FAILED) break;
		DWORD sz = 0;
		rc = GetOverlappedResult(hSlot, &ov, &sz, FALSE);
		if (rc) {
			buf[sz] = 0;
			printf("Message: %s\n", buf);
			ov = {};
			ov.hEvent = hEvent;
			rc = ReadFile(hSlot, buf, bufSize, 0, &ov);
			if (!rc && GetLastError() != ERROR_IO_PENDING) {
				break;
			}
		}
		else if (GetLastError() != ERROR_IO_INCOMPLETE) {
			break;
		}
		rc = WaitForSingleObject(hTimer, 0);
		if (rc==WAIT_OBJECT_0 ) {
			rc = SetWaitableTimer(hTimer, &dueTime, 0, NULL, NULL, 0);
			printf("Timer\n");
		}
		else if (rc != WAIT_TIMEOUT) {
			break;
		}
	} while (1);

	printf("Error: %i\n", GetLastError());

	return 0;
}




У меня в аналогичном коде
OVERLAPPED ov;
ov = {};
на 2005-й студии выдает ошибки на строчке такой как вторая.
(1734) : error C2059: syntax error : '{'
(1734) : error C2143: syntax error : missing ';' before '{'

Как извернуться?
...
Рейтинг: 0 / 0
11.04.2017, 06:41
    #39436237
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как совместить чтение Mailslot и WaitForMultipleObjects?
Дмитрий77Как извернуться?
Код: plaintext
1.
memset(&ov, 0, sizeof(ov));
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как совместить чтение Mailslot и WaitForMultipleObjects? / 20 сообщений из 20, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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