![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
XMLHTTP [D7, WinXP]
dima_q © (2008-06-30 13:13:00)Здравствуйте Мастера!
Есть COM библиотека служащая для общения с сервером. Общения происходит посредством xml по http. Для непосредственной связи используется объект XMLHTTP. Вопрос: Для работы с сервером, в моей либе создается отдельный поток. В потоке осуществляется вход в апартмент:
CoInitializeEx(nil, COINIT_APARTMENTTHREADED). После создания объекта c и присвоения всех свойств, вызывается методXMLHTTP.send(). Так вот при использовании потоковой модели STA(COINIT_APARTMENTTHREADED) запрос на сервер не идет, все остается висеть навечно. А при использовании MTA все благополучно проходит. Сам сервер XMLHTTP в реестре помечен как Appartment. Подскажите в чем может быть проблема. Почему при STA не вознивает никаких ошибок, но запрос не происходит? P.S.: использовать MTA нет возможности, из-за дальнейших проблем с клиентами моей либы.
dima_q (2008-07-02 10:26:00) [21]
> Трясти бубен, если код своего цикла показывать не желаешь)
Думаю бубен вряд ли поможет, а код, вот он:
TXMLHTTPThread = class(TThread)
private
m_xmlHTTP30 : MSXML3.TXMLHTTP30;
m_xmlHTTP40 : MSXML5.TXMLHTTP40;
m_xmlHTTP50 : MSXML5.TXMLHTTP50;
...
procedure ParseResponse();
function CheckOfTimeout(xmlHTTP : TXMLHTTP) : integer;// 0 - aborted, 1 - timed out, 4 - successful;
public
AlwaysSaveToFile : boolean;
constructor Create(async : boolean; url: string; sFileName: string = ''; stmPost: TIdMultipartFormDataStream = nil);
destructor Destroy(); override;
procedure Execute(); override;
...
end;
...
function TXMLHTTPThread.CheckOfTimeout(xmlHTTP: TXMLHTTP): integer;
var lastState, diff : integer;
ticks : cardinal;
rMsg : TMsg;
const ts : array [0..3] of integer = (60*1000,60*1000,10*60*1000,10*60*1000);
begin
Result := 4;
ticks := GetTickCount();
lastState := xmlHTTP.readyState;
while (lastState <> 4) do
begin
while (GetMessage (rMsg,0,0,0)) do DispatchMessage (rMsg);
Sleep(50);
if (GetTickCount() - ticks > ts[lastState]) then
begin
xmlHTTP.abort();
Result := 1;
Exit;
end;
if Terminated then
begin
xmlHTTP.abort();
Result := 0;
Exit;
end;
if (xmlHTTP.readyState > lastState) then
begin
ticks := GetTickCount();
lastState := xmlHTTP.readyState;
end;
end;
end;
constructor TXMLHTTPThread.Create(async : boolean; url: string; sFileName: string = ''; stmPost: TIdMultipartFormDataStream = nil);
begin
inherited Create(true);
m_xmlHTTP30 := nil;
m_xmlHTTP40 := nil;
m_xmlHTTP50 := nil;
...
end;
destructor TXMLHTTPThread.Destroy();
begin
...
end;
procedure TXMLHTTPThread.Execute();
var stmString : TStringStream;
i, rs : integer;
s : string;
begin
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
//COINIT_MULTITHREADED
//COINIT_APARTMENTTHREADED
case (XMLVersion) of
xml30: m_xmlHTTP30 := MSXML3.TXMLHTTP30.Create(nil);
xml40: m_xmlHTTP40 := MSXML5.TXMLHTTP40.Create(nil);
xml50: m_xmlHTTP50 := MSXML5.TXMLHTTP50.Create(nil);
xmlUnknown :
begin
m_error := 'Cannot access network : MSXML version 3.0 or higher is required';
m_completed := true;
CoUninitialize();
end;
end;
try
try
...
if (XMLVersion = xml30) then
begin
if (m_stmPost <> nil) then m_xmlHTTP30.send(m_postdata)
else m_xmlHTTP30.send();
if m_async then
case CheckOfTimeout(TXMLHTTP(m_xmlHTTP30)) of
0: begin m_error := 'aborted'; Exit; end;
1: begin m_error := 'timed out'; Exit; end;
end;
end else if (XMLVersion = xml40) then
begin
if (m_stmPost <> nil) then m_xmlHTTP40.send(m_postdata)
else m_xmlHTTP40.send();
if m_async then
begin
case CheckOfTimeout(TXMLHTTP(m_xmlHTTP40)) of
0: begin m_error := 'aborted'; Exit; end;
1: begin m_error := 'timed out'; Exit; end;
end;
end;
end else
begin
if (m_stmPost <> nil) then m_xmlHTTP50.send(m_postdata)
else m_xmlHTTP50.send();
if m_async then
begin
case CheckOfTimeout(TXMLHTTP(m_xmlHTTP50)) of
0: begin m_error := 'aborted'; Exit; end;
1: begin m_error := 'timed out'; Exit; end;
end;
end;
end;
if (XMLVersion = xml30) then
rs := m_xmlHTTP30.readyState
else if (XMLVersion = xml40) then
rs := m_xmlHTTP40.readyState
else
rs := m_xmlHTTP50.readyState;
if (rs >= 2) then // LOADED, STATUS is available
begin
if (XMLVersion = xml30) then
m_respCode := m_xmlHTTP30.status
else if (XMLVersion = xml40) then
m_respCode := m_xmlHTTP40.status
else
m_respCode := m_xmlHTTP50.status;
try
if (m_respCode >= 400) then
begin
m_error := 'ServerXMLHTTP returned an error : ';
if (XMLVersion = xml30) then
s := m_xmlHTTP30.statusText
else if (XMLVersion = xml40) then
s := m_xmlHTTP40.statusText
else
s := m_xmlHTTP50.statusText;
if (Length(s) > 0) then m_error := m_error + s
else m_error := m_error + ResponseCodeText(m_respCode);
end;
except end;
end;
if (rs = 4) then ParseResponse();
except
on ex : Exception do
begin
m_error := {'ServerXMLHTTP has returned an error: ' +} ex.Message;
end;
end;
finally
m_completed := true;
if (XMLVersion = xml30) then
FreeAndNil(m_xmlHTTP30)
else if (XMLVersion = xml40) then
FreeAndNil(m_xmlHTTP40)
else
FreeAndNil(m_xmlHTTP50);
CoUninitialize();
end;
end;
end.
Сергей М. (2008-07-02 10:16:00) [22]
> Незнаю, что делать
Ну как что ?
Трясти бубен, если код своего цикла показывать не желаешь)
dima_q (2008-07-02 09:42:00) [23]
> Кого ?!
Цикл обработки сообщений. Попробовал, не работает все равно. Незнаю, что делать:(
Сергей М. (2008-07-01 16:47:00) [24]
> Мот я просто не так добавлял его
Кого ?!
dima_q (2008-07-01 09:35:00) [25]
> Сергей М. ©
Буду копать в сторону цикла обработки сообщений в потоке. Мот я просто не так добавлял его, попробую еще раз, огромное спасибо!
Сергей М. (2008-06-30 19:47:00) [26]
> В синхронном режиме сенд проходит нормально
Отсюда и вывод: threading model тут совершенно ни причем.
Похоже что XMLHTTP в асинхр.режиме заточен на нотификацию посредством оконных сообщений. И, поскольку в теле цикла ты не предпринимаешь никаких телодвижений по выборке/диспетчеризации оных, ожидать onreadystatechange или изменение readyState придется до второго пришествия.
dima_q (2008-06-30 19:27:00) [27]В синхронном режиме сенд проходит нормально, не знаю что делать...
dima_q (2008-06-30 18:30:00) [28]Пробовал при асинхронном запросе вешать onreadystatechange, не происходит события. Сейчас попробую, что скажет синхронный.
clickmaker (2008-06-30 18:16:00) [29]погодь... насколько я знаю, там либо синхронно, тогда send не вернет, пока не выполнится, либо асинхронно, тогда надо вешать onreadystatechange
попробуй второй вариант
dima_q (2008-06-30 18:09:00) [30]
> clickmaker © (30.06.08 17:59) [7]
> onreadystatechange используешь или синхронно?
Не использую. Просто в цикле проверяю XMLHTTP.readyState.
clickmaker (2008-06-30 17:59:00) [31]onreadystatechange используешь или синхронно?
dima_q (2008-06-30 17:53:00) [32]И статус (XMLHTTP.readyStatus) не изменяется никогда, он всегда 1. Хотя сервер доступен.
dima_q (2008-06-30 17:51:00) [33]Исключения обрабатываю, их нет. Висит, в смысле на сервере, он тоже мой, стоит бряка, но запрос не доходит до него.
Сергей М. (2008-06-30 16:37:00) [34]
> тупо не посылает запрос.
С чего ты взял, что "не посылает" ?
А если и не посылает, то что значит "все .. висеть" ?
ты исключения обрабатываешь ?
dima_q (2008-06-30 13:37:00) [35]Вся проблема в том, что при работе с CoInitializeEx(nil, COINIT_APARTMENTTHREADED) нет никаких ошибок. Просто тупо не посылает запрос.
dima_q (2008-06-30 13:35:00) [36]
> Сергей М. © (30.06.08 13:29) [1]
> А при CoInitialize(nil) работает ?
Нет не работает. CoInitialize(nil) идентичен CoInitializeEx(nil, COINIT_APARTMENTTHREADED), это его сокращенный вызов.
Сергей М. (2008-06-30 13:29:00) [37]А при CoInitialize(nil) работает ?