Асинхронный обратный вызов WinHttp в vb6

У меня есть служба vb6, которая использует синхронные вызовы WinHttp на удаленный сервер. Эти вызовы блокируют службу в периоды, когда возникают проблемы с подключением (сеть/Интернет и т. д.).

Моя задача — реализовать асинхронные вызовы WinHttp.

Первый шаг, я пытаюсь выяснить преобразования из С++ в vb6. Принимая во внимание, что я никогда раньше не писал ни строчки на C++.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa383917(v=vs.85).aspx

typedef void ( CALLBACK *WINHTTP_STATUS_CALLBACK)(
_In_  HINTERNET hInternet,
_In_  DWORD_PTR dwContext,
_In_  DWORD dwInternetStatus,
_In_  LPVOID lpvStatusInformation,
_In_  DWORD dwStatusInformationLength
);

Это моя попытка:

Public Declare Function WINHTTP_STATUS_CALLBACK Lib "winhttp.dll"
(ByVal hSession As Long, dwContext As Long, dwInternetStatus As Integer,
lpvStatusInformation As Long, dwStatusInformationLength As Integer)

Я понятия не имею, правильно ли это, и, к сожалению, я не могу проверить это, пока не продвинусь немного дальше.

Следующий — WinHttpSetStatusCallback.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384115(v=vs.85).aspx

WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback(
_In_        HINTERNET hInternet,
_In_        WINHTTP_STATUS_CALLBACK lpfnInternetCallback,
_In_        DWORD dwNotificationFlags,
_Reserved_  DWORD_PTR dwReserved
);

Это моя попытка:

Public Declare Function WinHttpSetStatusCallback Lib "winhttp.dll"
(ByVal hInternet As Long, ByVal lpfnInternetCallback As Long,
ByVal dwNotificationFlags As Long, ByVal dwReserved As Long) As Long

Я действительно не знаю, правильны ли мои преобразования. Кто-нибудь может это проверить?

Далее, я не знаю, как реализовать WinHttpSetStatusCallback - например, я не знаю, правильно ли у меня указан указатель на функцию обратного вызова.

_In_        WINHTTP_STATUS_CALLBACK lpfnInternetCallback,

конвертировано в:

ByVal lpfnInternetCallback As Long

Я тоже не уверен, что у меня это правильно.

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

Public Function AsyncCallback(
                        ByVal hInternet As Long,
                        dwContext As Long,
                        dwInternetStatus As Long,
                        lpvStatusInformation As Long,
                        dwStatusInformationLength As Long)
    //code in here
End Function

Затем, наконец, будет интересно все это подключить. Но сначала я должен убедиться, что у меня правильные основы, иначе я не могу ожидать, что это волшебным образом «сработает».

Пример MSDN C++ выглядит следующим образом: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384115(v=vs.85).aspx

// Install the status callback function.
WINHTTP_STATUS_CALLBACK isCallback = WinHttpSetStatusCallback( hSession,
                                           (WINHTTP_STATUS_CALLBACK)AsyncCallback,
                                           WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 
                                           NULL);

Как определить указатель на функцию AsyncCallback в vb6?


person Ben    schedule 12.08.2013    source источник
comment
Класс WinHttp.WinHttpRequest представляет собой довольно тонкую оболочку низкоуровневых вызовов WinHttp и предоставляет события вместо обратных вызовов. Есть ли причина, по которой вы просто не используете его вместо этого?   -  person Bob77    schedule 12.08.2013
comment
Это GET-запросы? Если да, то почему бы просто не выполнить асинхронный HTTP GET простым способом? См. мой ответ здесь   -  person MarkJ    schedule 12.08.2013
comment
@MarkJ спасибо за предложение, выглядит интересно. Знаете ли вы, как я могу реализовать UserControl без формы? то есть автоматическая служба?   -  person Ben    schedule 13.08.2013
comment
@ Bob77 Я рассматривал возможность WinHttp.WinHttpRequest, однако он не обеспечивает такой гибкости, как непосредственно WinHttp. Служба уже «построена» с большим количеством функций WinHttp, перенос ее на WinHttp.WinHttpRequest потребует значительной модернизации и, возможно, сокращения некоторых параметров. Кроме того, моя задача состоит только в том, чтобы реализовать Asynchronous, а не полностью переписать то, что уже разработано.   -  person Ben    schedule 13.08.2013
comment
Даже если вы успешно установите обратный вызов (используйте оператор AddressOf), вы обречены. Поток обратного вызова не имеет инициализированного COM, он не будет работать в квартире вашего потока пользовательского интерфейса, и ваша функция должна быть потокобезопасной. Есть только несколько простых операторов VB6, которые вы сможете успешно выполнить внутри него.   -  person Bob77    schedule 13.08.2013
comment
Привет, @Bob77, у сервиса нет пользовательского интерфейса. Единственный код, который мне нужен внутри функции обратного вызова, — это оператор select, проверяющий уведомление, задающий глобальное логическое значение и проверяющий, получила ли служба уведомление об остановке. Если получено уведомление об остановке, служба должна ответить — с этой проблемой в настоящее время сталкиваются, когда операции блокируются с помощью синхронной обработки.   -  person Ben    schedule 14.08.2013
comment
Весь код, который вы можете написать в VB6, выполняется в потоке пользовательского интерфейса, независимо от того, считаете ли вы, что у вас есть пользовательский интерфейс или нет. Речь идет не о наличии формы, все программы VB6 имеют скрытое окно верхнего уровня и цикл сообщений. Почти все, что вы можете сделать в этом виде обратного вызова, — это несколько условных операторов, которые устанавливают переменные в статическом модуле, а затем завершают работу. Остальная часть вашего кода выполняется в потоке пользовательского интерфейса, и ему нужно будет опрашивать результаты (изменения в статических данных).   -  person Bob77    schedule 14.08.2013
comment
Ладно, понял. Я хотел убедиться, что вы знаете, что я не пытаюсь установить строку состояния или что-то в этом роде. Тем не менее, я хочу только запустить несколько условных операторов и установить глобальное логическое значение - вот и все. Итак, похоже, что Async будет делать то, что я хочу. Итак, теперь вопрос в том, можете ли вы ответить на вопрос?   -  person Ben    schedule 15.08.2013
comment
Вы можете ответить на вопрос @Bob77?   -  person Ben    schedule 17.08.2013
comment
Я уже сделал. Используйте оператор AddressOf msdn.microsoft.com/en -us/library/aa242738(v=VS.60).aspx   -  person Bob77    schedule 17.08.2013
comment
Глобальные переменные в VB6 на самом деле являются локальными для потока, поэтому вы не можете установить флаг из потока обратного вызова и опросить его из потока пользовательского интерфейса. Используйте события API или подобные объекты.   -  person wqw    schedule 19.08.2013