Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.05.13;
Скачать: [xml.tar.bz2];

Вниз

Вопрос по энергосбережению и экранной заставке. Проблема.   Найти похожие ветки 

 
DVM ©   (2007-04-16 10:54) [0]

Есть программа, которая постоянно должна работать в фоновом режиме. Кратко: принимает данные по сети и пишет файл. Компьютер не трогается некоторое время - появляется заставка. И все... Обмен данными прекращается. Соединение не разрывается, но функция Select возвращает всегда ошибку и все. Как только заставка убирается работа возобновляется. WinXPSP2. В параметрах энергосбережения указано "Включен постоянно".

Прием данных ведется во вторичном потоке.

В чем может быть проблема?


 
Сергей М. ©   (2007-04-16 11:04) [1]


> ошибку и все


Что это за ошибка "и все" ?)


 
DVM ©   (2007-04-16 11:19) [2]


> Что это за ошибка

select возвращает SOCKET_ERROR, по сведениям WSAGetLastError это
WSAENOTSOCK


 
Чапаев ©   (2007-04-16 11:20) [3]

> > ошибку и все
> Что это за ошибка "и все" ?)
Это не ошибка "и все", а вместе с ошибкой возвращается ВСЁ.

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


 
DVM ©   (2007-04-16 11:26) [4]


> Чапаев ©   (16.04.07 11:20) [3]

Есть что сказать по делу? Зачитывать описание ошибки из MSDN не требуется.

Может играет роль а может и нет, но поток создается с FThread.Priority := tpLower;


 
Чапаев ©   (2007-04-16 11:26) [5]

> [4] DVM ©   (16.04.07 11:26)
Так ведь конференция "Прочее", а не "Сети".


 
Чапаев ©   (2007-04-16 11:29) [6]

Вообще думается, что-то с рабочими станциями и десктопами связано. Программа эта не сервис случайно?


 
DVM ©   (2007-04-16 11:29) [7]


> Чапаев ©   (16.04.07 11:26) [5]

Тут не совсем по сетям. Работа программы приостанавливается как бы при появлении заставки. Или вторичные потоки приостанавливаются что-ли.


 
DVM ©   (2007-04-16 11:30) [8]


> Программа эта не сервис случайно?

Нет не сервис. Хотя сервисом ей быть не помешало бы:).


 
DVM ©   (2007-04-16 11:37) [9]

с Select разобрался - это сам сервер разрывает соединение, потому как клиент бездействует. Но вот почему поток с клиентом бездействует при включенной заставке - ВОПРОС!


 
SlymRO ©   (2007-04-16 11:44) [10]

В Outpost имеется галочка "Блокировать весь сетевой трафик при активации программы заставки" :)


 
DVM ©   (2007-04-16 11:58) [11]


> SlymRO ©   (16.04.07 11:44) [10]

Outpost не установлен, установлен, но выключен KAV6 + включен встроенный файерволл.


 
Сергей М. ©   (2007-04-16 12:09) [12]


> DVM ©   (16.04.07 10:54)


WSAAsyncSelect используется ?


 
DVM ©   (2007-04-16 12:15) [13]


> WSAAsyncSelect используется

нет.


 
Сергей М. ©   (2007-04-16 12:25) [14]


> DVM ©   (16.04.07 12:15) [13]


Каким образом твой транспорт завязан на оконные сообщения ?


 
DVM ©   (2007-04-16 12:32) [15]


> Сергей М. ©   (16.04.07 12:25) [14]

Во вторичном потоке чтение происходит так:


function TInputThread.ReadData(ABuffer: TBuffer; BytesExpected: integer): integer;
const
 MaxLen = 262144;
var
 TotalBytesToRead, Found, TotalBytesRead, BytesToRead, BytesRead: integer;
 Rfds: TFDSet;
 TempBuff: array [0..Pred(MaxLen)] of Char;
begin
 FD_ZERO(Rfds);
 FD_SET(FSock, Rfds);
 Found := select(FSock, @Rfds, nil, nil, @FTimeout);
 if Found = 0 then
   begin
     Result := -1;
     exit;
   end
 else
   if Found = SOCKET_ERROR then
     begin
       Result := -1;
       exit;
     end;
 TotalBytesToRead := 0;
 if BytesExpected <> 0 then
   begin
     TotalBytesToRead := BytesExpected;
   end
 else
   begin
     if ioctlsocket(FSock, FIONREAD, TotalBytesToRead) = SOCKET_ERROR then
       begin
         Result := -1;
         exit;
       end;
     if TotalBytesToRead = 0  then
       begin
         SocketDisconnect();
         Result := 0;
         exit;
       end;
   end;
 TotalBytesRead := 0;
 repeat
   if TotalBytesToRead > MaxLen then
     BytesToRead := MaxLen
   else
     BytesToRead := TotalBytesToRead;
   ZeroMemory(@TempBuff[0], MaxLen);
   BytesRead := recv(FSock, TempBuff, BytesToRead, 0);
   if BytesRead = SOCKET_ERROR then
     begin
       SocketDisconnect();
       Result := -1;
       exit;
     end
   else
     if BytesRead = 0 then
       begin
         SocketDisconnect();
         Result := 0;
         exit;
       end
     else
       begin
         if ABuffer.Size >= 2097152 then
           begin
             SocketDisconnect();
             Result := -1;
             exit;
           end;
         ABuffer.Append(@TempBuff[0], BytesRead);
         TotalBytesRead := TotalBytesRead + BytesRead;
         TotalBytesToRead := TotalBytesToRead - BytesRead;
       end;
 until TotalBytesToRead <= 0;
 Result := TotalBytesRead;
end;


Это крутится в цикле, если происходит дисконнект - соединение восстанавливается. Функции коннекта и дисконнекта не привожу - они тут не при чем.

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


 
Сергей М. ©   (2007-04-16 12:39) [16]

А что делает осн.поток при получении блока ?


 
DVM ©   (2007-04-16 12:40) [17]


> А что делает осн.поток при получении блока ?

На диск его записывает в предварительно открытый файл.


 
Сергей М. ©   (2007-04-16 12:42) [18]

А где же тогда клиент проявляет "активность" ?
Где и при каких условиях он что-то отправляет серверу ?


 
DVM ©   (2007-04-16 12:50) [19]


> А где же тогда клиент проявляет "активность" ?

В том цикле, который крутится в доп потоке клиент делает HTTP - запрос после того как выделен блок данных, чтобы сервер слал следующий.

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

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


 
Сергей М. ©   (2007-04-16 12:58) [20]


> после того как выделен блок данных


Как же он будет "выделен", если select вернул отказ (что, как ты утверждаешь,  есть следствие разрыва соединения по инициативе сервера) и при этом процедура ReadData немедленно завершается ?

Что делает вызывающий код по возврату из ReadData c результатом -1 ?


 
DVM ©   (2007-04-16 13:14) [21]


> Как же он будет "выделен", если select вернул отказ (что,
>  как ты утверждаешь,  есть следствие разрыва соединения
> по инициативе сервера) и при этом процедура ReadData немедленно
> завершается ?

Если ReаdData вернет -1 то клиент отключает сокет, ждет пару секунд и пытается подключить сокет вновь, затем при удаче делает запрос, потом опять начинает читать ответ сервера если таковой есть.

Если ReadData возвращает 0 это означает, что сервер выдал все имеющиеся на данный момент у него данные - ищем там маркеры - если блок найден, высылаем его в основной поток, далее дисконнект с сервером и пошли заново - коннект, запрос, чтение.

Если ReadData возвращает > 0, продолжаем вызывать ReadData до тех пор пока в буфере не образуется целый блок, затем высылаем его в основной поток, после чего выкидываем целый блок из буфера а серверу посылаем запрос, чтобы слал следующий блок.

Код привести не могу, т.к. он длинный а к делу относится далеко не вся его чать.

С логикой приема проблем нет - все же прекрасно работает без заставки и проблема только при появлении оной.


 
Alex Konshin ©   (2007-04-16 13:15) [22]

Ну не используй ты окна.
Используй Winsock2 возможности работать с сокетом без окна.


 
DVM ©   (2007-04-16 13:20) [23]


> Ну не используй ты окна.

Да я с сокетом без окон и работаю. Это уже готовый результат пересылается в окно, а там уже и записывается. Окно одно - в основном потоке.


 
Сергей М. ©   (2007-04-16 13:33) [24]


> ждет пару секунд


Надо понимать, не без помощи TTimer ?

Пойми, все идет к проблеме с оконными сообщениями.


 
DVM ©   (2007-04-16 13:39) [25]


> Надо понимать, не без помощи TTimer ?

Без помощи таймера он ждет, конечно же. Он просто sleep(2000) делает. Хочу повторить Sleep в потоке принимающем даннные именно.

Вторичный поток не знает и не использует НИЧЕГО короме хэндла основного окна из основного потока. Ничего относящегося к VCL (кроме TThread самого).


 
Сергей М. ©   (2007-04-16 13:45) [26]

Результаты вызовов connect(), send() ты протоколируешь ?
Что показывает протокол ?


 
isasa ©   (2007-04-16 13:51) [27]

Тут эта, тупой вопрос. А "без заставки" все работает?


 
DVM ©   (2007-04-16 13:56) [28]


> А "без заставки" все работает?

Да, конечно же.


> Сергей М. ©   (16.04.07 13:45) [26]
> Результаты вызовов connect(), send() ты протоколируешь ?
>


Я кажется нашел проблему. Почему то пересоздается окно при всех этих манипуляциях с заставками/мониторами. Как раз то окно, которому поток должен слать сообщение. Сообщения уходят в никуда.


 
Сергей М. ©   (2007-04-16 13:58) [29]


> Как раз то окно, которому поток должен слать сообщение.
> Сообщения уходят в никуда


ну даже если и в никуда - какое отношение это имеет к активности клиента ?
Ведь ты же утверждаешь, что осн.поток НЕ имеет никакого отношения к транспорту ?


 
DVM ©   (2007-04-16 14:05) [30]


> ну даже если и в никуда - какое отношение это имеет к активности
> клиента ?
> Ведь ты же утверждаешь, что осн.поток НЕ имеет никакого
> отношения к транспорту ?

Ну сказать, что совсем не имеет нельзя. Не совсем я правильно описал ситуацию. Связь эта есть - и она как раз через Result в SendMessage(). Поток получает неверный результ и крутится вхолостую - не делает запросы к серверу (так в коде описано). Вот и грабли.

Всем спасибо. Сделал уведомление потока об изменении хэндла - вроде работает.


 
isasa ©   (2007-04-16 14:18) [31]

DVM ©   (16.04.07 13:56) [28]
Да, конечно же.


Я к чему спросил.
Как-то столкнулся с неприятным моментом. Обычный SQL клиент(Delphi+ADO) и длительное задание(оставляли на ночь), протокол выполнения писалсяв файл(сколько сделано, сколько осталось...). Так вот, во время работы при старте скрин сейвера или заставки обмен замирал(хоч на TCP/IP, хоч на pipes). С тех пор, я заставки и сейверы при такой работе вырубаю. :)


 
Сергей М. ©   (2007-04-16 14:28) [32]


> Почему то пересоздается окно


Хм..

Вот смотрю я исходники юнита forms в D7 VCL и чешу репу насчет "почемуты" - метод TWinControl.RecreateWnd "самопроизвольно" нигде не вызывается - всюду, где наблюдается его вызов, это связано с явным программным изменением тех или иных публичных свойтв объекта-наследника этого класса.


 
DVM ©   (2007-04-16 14:40) [33]


> Сергей М. ©   (16.04.07 14:28) [32]


> Хм..

Код основного потока я полностью внимательно не глядел (не я его писал, я переделываю) - может там и есть какая либо причина приводящая к пересозданию окна (она там конечно должна быть). Поищу чуть позже.


 
Сергей М. ©   (2007-04-16 14:49) [34]


> DVM ©   (16.04.07 14:40) [33]


Но в таком случае каким образом ты "ловишь" момент пересоздания целевого окна ? Каким-то событием руководствуешься или где ?


 
DVM ©   (2007-04-16 15:06) [35]


> Сергей М. ©   (16.04.07 14:49) [34]


procedure TMySuperPuperWindow.CreateHandle;
begin
 inherited;
 if FThread <> nil then FThread.Handle := self.Handle;
end;


 
DVM ©   (2007-04-16 15:09) [36]

Само собой

protected
   procedure CreateHandle; override;


 
Сергей М. ©   (2007-04-16 15:10) [37]


> DVM ©   (16.04.07 15:06) [35]


Врешь)

CreateHandle - статический метод)


> FThread.Handle


Если FThread есть TThread, то опять врешь - его св-во Handle не имеет ничего общего с оконными хэндлами.


 
Сергей М. ©   (2007-04-16 15:11) [38]

TMySuperPuperWindow - чей наследник ?


 
DVM ©   (2007-04-16 15:18) [39]


> Сергей М. ©   (16.04.07 15:10) [37]

Я не знаю, чего вы добиваетесь, но извольте:

> Врешь)
>
> CreateHandle - статический метод)



unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs;

type
 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
 protected
   procedure CreateHandle; override;
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CreateHandle;
begin
inherited;
Windows.Beep(500,50);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

end.


Даже на примере формы прекрасно бибикает!


> TMySuperPuperWindow - чей наследник ?

TCustomControl


> > FThread.Handle
>
>
> Если FThread есть TThread, то опять врешь - его св-во Handle
> не имеет ничего общего с оконными хэндлами.

Описка это. Там надо FThread.FHandle := self.Handle;

И, придвидя следующие придирки, скажу сразу обращение к FThread.FHandle что на чтение, что на запись завернуто в критические секции в самом FThread.


 
DVM ©   (2007-04-16 15:22) [40]


> Если FThread есть TThread, то опять врешь - его св-во Handle
> не имеет ничего общего с оконными хэндлами.

У объекта TThread свойства Handle нет!



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2007.05.13;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.042 c
15-1176302795
Mr. D.
2007-04-11 18:46
2007.05.13
Изменение стиля поведения TDBGrid


2-1176714827
MVA`
2007-04-16 13:13
2007.05.13
Jpeg


2-1177340248
Никитин К
2007-04-23 18:57
2007.05.13
выручите, плиз! Не представляю как делать...


4-1166019247
Max_2006
2006-12-13 17:14
2007.05.13
DateTiMePicker на API


15-1176693141
DelphiN!
2007-04-16 07:12
2007.05.13
Спам о заработке в Интернете





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский