Главная страница
    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 нет!


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

Ах вон оно что !
Пердуперждать надо, что ты наследуешь чью-то форму)


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


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


Indicates the thread"s handle (Windows only).

Delphi syntax:

property Handle: THandle;

C++ syntax:

__property int Handle = {read=FHandle, nodefault};

Description

On Windows, use Handle for calling Win32 API functions for thread manipulation.

The Handle property is not available on Linux.


Это я сам придумал ?)


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


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

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

TMyThread = class(TThread)
 private
   FHandle: THandle;
 ...
 ...
   procedure SetHandle(const AHandle: THandle);
   function GetHandle: THandle;
 ...
published
   property Handle: THandle read GetHandle write SetHandle;
 ...
end;

так прокатило вполне.


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


> Причем странно, что данная описка никак не повлияла на работу


Ничего странного.

TThread.Handle в твоем случае не имеет ничего общего с TMyThread.Handle


> published


А уж начерта тут именно published - это вообще загадка природы)


 
DVM ©   (2007-04-16 15:47) [45]


> А уж начерта тут именно published - это вообще загадка природы)

Ну published это конечно лишнее. Copy/Paste виновато.:)


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


> DVM


Вот и получается, что подозрительно многое виновато в твоих собственных проблемах)


 
DVM ©   (2007-04-16 15:53) [47]


> в твоих собственных проблемах

Ничего подобного. Проблема как была одна - так и осталась одна (и устранена) - пересоздание окна.



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

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

Наверх





Память: 0.59 MB
Время: 0.048 c
4-1164404967
Kaharin
2006-11-25 00:49
2007.05.13
Как определить работает дисплей (монитор) или нет


15-1176473077
Desdechado
2007-04-13 18:04
2007.05.13
Куда подевались остальные страницы форума?


15-1176274427
ocean
2007-04-11 10:53
2007.05.13
Действительно, куда там Донцовой


2-1177166356
Кузнецов
2007-04-21 18:39
2007.05.13
Указатель


2-1177399226
webpauk
2007-04-24 11:20
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский