EnableExplicit Procedure Core_UpdateTracker_Thread(*x) ; Поток обновления трекеров - получения информвации о пирах и других данных. Protected Info.ProgramStatus_Network_TrackerTaskList Protected KillThread.a, x.a KillThread = 0 Repeat WaitSemaphore(G_ProgramMiscInfo\Network\TrackerTask_Semaphore) ; Нужно обработать список заданий. Repeat If G_ProgramMiscInfo\Network\TrackerTask_EndThread = 1 And G_ProgramMiscInfo\ProgEndSate <> 0 ; Надо будет завершить поток! KillThread = 1 EndIf ClearStructure(@Info, ProgramStatus_Network_TrackerTaskList) If Test_LockMutex(G_ProgramMiscInfo\Network\TrackerTask_Mutex, 100) = #True If ListSize(G_ProgramMiscInfo\Network\TrackerTask_List())<=0 ; Список пуст. UnlockMutex(G_ProgramMiscInfo\Network\TrackerTask_Mutex) Break EndIf x=0 If KillThread = 0 ; Обычаня обработка заданий ; ForEach G_ProgramMiscInfo\Network\TrackerTask_List() If G_ProgramMiscInfo\Network\TrackerTask_List()\Active = 1 ; Хз, откуда взялось активное задание - в корзину его! DeleteElement(G_ProgramMiscInfo\Network\TrackerTask_List()) Continue EndIf If G_ProgramMiscInfo\Network\TrackerTask_List()\Status=#Tracker_Empty Or G_ProgramMiscInfo\Network\TrackerTask_List()\Status=#Tracker_Started Or G_ProgramMiscInfo\Network\TrackerTask_List()\Status=#Tracker_Stopped Or G_ProgramMiscInfo\Network\TrackerTask_List()\Status=#Tracker_Completed Info\INFO_Hash = G_ProgramMiscInfo\Network\TrackerTask_List()\INFO_Hash Info\Server = G_ProgramMiscInfo\Network\TrackerTask_List()\Server G_ProgramMiscInfo\Network\TrackerTask_List()\Active = 1 x=1 Break EndIf Next Else ; Поскольку программа завершается, то обрабатываем только задания информирования трекера об закрытии торрент-клиента. ForEach G_ProgramMiscInfo\Network\TrackerTask_List() If G_ProgramMiscInfo\Network\TrackerTask_List()\Status=#Tracker_Stopped G_ProgramMiscInfo\Network\TrackerTask_List()\Status=#Tracker_Empty Info\INFO_Hash = G_ProgramMiscInfo\Network\TrackerTask_List()\INFO_Hash Info\Server = G_ProgramMiscInfo\Network\TrackerTask_List()\Server G_ProgramMiscInfo\Network\TrackerTask_List()\Active = 1 x=1 Break Else DeleteElement(G_ProgramMiscInfo\Network\TrackerTask_List()) ; Это задание обрабатывать не нужно. EndIf Next EndIf If x=0 ClearList(G_ProgramMiscInfo\Network\TrackerTask_List()) UnlockMutex(G_ProgramMiscInfo\Network\TrackerTask_Mutex) Break EndIf UnlockMutex(G_ProgramMiscInfo\Network\TrackerTask_Mutex) Else ; Ошибка захвата мьютекса. Delay(2) Continue EndIf Tracker_SetTracker(@Info) If Test_LockMutex(G_ProgramMiscInfo\Network\TrackerTask_Mutex, 800) ForEach G_ProgramMiscInfo\Network\TrackerTask_List() If G_ProgramMiscInfo\Network\TrackerTask_List()\Active = 1 If G_ProgramMiscInfo\Network\TrackerTask_List()\INFO_Hash = Info\INFO_Hash And G_ProgramMiscInfo\Network\TrackerTask_List()\Server = Info\Server DeleteElement(G_ProgramMiscInfo\Network\TrackerTask_List()) Break EndIf EndIf Next UnlockMutex(G_ProgramMiscInfo\Network\TrackerTask_Mutex) EndIf ForEver Delay(2) Until KillThread = 1 EndProcedure Procedure Core_DomainsPeer_Thread(*x) ; Поток получения доменного имени пира и присвоения номера флага-иконки в таблице пиров на панели информации. Protected Info.ProgramStatus_Network_DomainsPeer Protected HostName.s, Flag.DomainsInfo, x Static NewList CacheHostName.GetIcon_Extension() Repeat WaitSemaphore(G_ProgramMiscInfo\Network\DomainsPeer_Semaphore) If G_ProgramMiscInfo\ProgEndSate <> 0 ; Прога закрывается - завершить работу потока. Break EndIf Repeat If ListSize(CacheHostName())>=1000 If LastElement(CacheHostName()) DeleteElement(CacheHostName()) EndIf EndIf ClearStructure(@Info, ProgramStatus_Network_DomainsPeer) If Test_LockMutex(G_ProgramMiscInfo\Network\DomainsPeer_Mutex, 100)=#True If ListSize(G_ProgramMiscInfo\Network\DomainsPeer_TaskList())<=0 ; Список пуст. UnlockMutex(G_ProgramMiscInfo\Network\DomainsPeer_Mutex) Break EndIf ;FirstElement(G_ProgramMiscInfo\Network\DomainsPeer_TaskList()) ; Текущий - первый элемент списка. ForEach G_ProgramMiscInfo\Network\DomainsPeer_TaskList() If G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\Active = 1 DeleteElement(G_ProgramMiscInfo\Network\DomainsPeer_TaskList()) Continue EndIf Info\INFO_Hash = G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\INFO_Hash Info\IP_Peer = G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\IP_Peer Info\IP = G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\IP G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\Active = 1 Break Next UnlockMutex(G_ProgramMiscInfo\Network\DomainsPeer_Mutex) If Info\INFO_Hash<>"" And Info\IP_Peer<>"" x=0 ForEach CacheHostName() If CacheHostName()\IconID = Info\IP If CacheHostName()\Part<>"" HostName = CacheHostName()\Part x=1 EndIf Break EndIf Next If x=0 HostName = GetHostNameByIP(Info\IP_Peer) If HostName<>"" FirstElement(CacheHostName()) If InsertElement(CacheHostName()) CacheHostName()\IconID = Info\IP CacheHostName()\Part = HostName EndIf EndIf EndIf Flag\Domain = HostName If HostName = "" HostName = Info\IP_Peer EndIf Flag\IP = Info\IP GetImageIndex_FlagImage(@Flag) If G_ProgramMiscInfo\ProgEndSate <> 0 ; Прога закрывается - завершить работу потока. Break 2 EndIf If Test_LockMutex(G_TorrentList\Mutex, 200) = #True ForEach G_TorrentList\TorrentList() If G_TorrentList\TorrentList()\TorrentFile\INFO_Hash = Info\INFO_Hash ForEach G_TorrentList\TorrentList()\Network\PeerList() If G_TorrentList\TorrentList()\Network\PeerList()\IP$ = Info\IP_Peer G_TorrentList\TorrentList()\Network\PeerList()\Out_Table\Domains = HostName G_TorrentList\TorrentList()\Network\PeerList()\Out_Table\Flag = Flag\ImageListIndex G_TorrentList\TorrentList()\Network\PeerList()\Out_Table\Local = Flag\Comment Break EndIf Next Break EndIf Next UnlockMutex(G_TorrentList\Mutex) EndIf EndIf Else ; Ошибка захвата мьютекса. Delay(2) Continue EndIf If Test_LockMutex(G_ProgramMiscInfo\Network\DomainsPeer_Mutex, 800) = #True ForEach G_ProgramMiscInfo\Network\DomainsPeer_TaskList() If G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\Active = 1 If G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\INFO_Hash = Info\INFO_Hash And G_ProgramMiscInfo\Network\DomainsPeer_TaskList()\IP_Peer = Info\IP_Peer DeleteElement(G_ProgramMiscInfo\Network\DomainsPeer_TaskList()) Break EndIf EndIf Next UnlockMutex(G_ProgramMiscInfo\Network\DomainsPeer_Mutex) EndIf ForEver Delay(32) ForEver EndProcedure Procedure WSA_OpenNetworkConnection(ip.s, port.l, *EventID.Integer) Protected *ptr, clientService.sockaddr_in, argp.l, Socket.i, *Mem, Count Protected sin_addr, *Socket_2, Heap Protected WSACreateEvent.WSACreateEvent=G_ProgramMiscInfo\Network\WSA\WSACreateEvent Protected WSACloseEvent.WSACloseEvent=G_ProgramMiscInfo\Network\WSA\WSACloseEvent Protected WSAEventSelect.WSAEventSelect=G_ProgramMiscInfo\Network\WSA\WSAEventSelect Count = StringByteLength(ip, #PB_Ascii) *Mem = AllocateMemory(Count+4) If *Mem FillMemory(*Mem, Count+4, 0, #PB_Byte) PokeS(*Mem, ip, -1, #PB_Ascii) sin_addr=inet_addr_(*Mem) FreeMemory(*Mem) Else ProcedureReturn #False EndIf Socket = SOCKET_(#AF_INET, #SOCK_STREAM, #IPPROTO_TCP) If Socket = #INVALID_SOCKET ProcedureReturn #False EndIf argp=01 ; Asynchronous socket. If ioctlsocket_(Socket, #FIONBIO, @argp)<>#SOCKET_ERROR *ptr = clientService.sockaddr_in clientService\sin_family = #AF_INET clientService\sin_addr = sin_addr clientService\sin_port = htons_(port) CompilerIf #PB_Compiler_Processor = #PB_Processor_x86 !MOV Eax, dword [_PB_MemoryBase] !MOV dword [p.v_Heap], Eax CompilerElse !MOV rax, [_PB_MemoryBase] !MOV [p.v_Heap], rax CompilerEndIf CompilerIf #PB_Compiler_Processor = #PB_Processor_x86 *Socket_2=HeapAlloc_(Heap, #HEAP_ZERO_MEMORY, $10) CompilerElse *Socket_2=HeapAlloc_(Heap, #HEAP_ZERO_MEMORY, $17) PokeI(*Socket_2+$10, 0) CompilerEndIf If *Socket_2 PokeL(*Socket_2, 1) PokeL(*Socket_2+8, Socket) If *EventID *EventID\i=#WSA_INVALID_EVENT *EventID\i=WSACreateEvent() If *EventID\i<>#WSA_INVALID_EVENT If WSAEventSelect(Socket, *EventID\i, #FD_CONNECT)=#SOCKET_ERROR WSACloseEvent(*EventID\i) Goto WSA_OpenNetworkConnection_Err EndIf Else WSA_OpenNetworkConnection_Err: *EventID\i=0 closesocket_(Socket) HeapFree_(Heap, 0, *Socket_2) *Socket_2=0 ProcedureReturn #False EndIf EndIf connect_(Socket, *Ptr, SizeOf(sockaddr_in)) ProcedureReturn *Socket_2 Else closesocket_(Socket) ProcedureReturn #False EndIf Else closesocket_(Socket) ProcedureReturn #False EndIf EndProcedure Procedure.a Core_Network_ConnectPeer_SetResult(ConnectID, *Info.ProgramStatus_Network_ConnectPeer) ; Запись в список, результата конекта с пиром. Protected x.a LockMutex(G_ProgramMiscInfo\Network\ConnectPeer_Mutex) x=#False ForEach G_ProgramMiscInfo\Network\ConnectPeer_List() If G_ProgramMiscInfo\Network\ConnectPeer_List()\Active = #True If G_ProgramMiscInfo\Network\ConnectPeer_List()\INFO_Hash = *Info\INFO_Hash And G_ProgramMiscInfo\Network\ConnectPeer_List()\IP_Peer=*Info\IP_Peer And G_ProgramMiscInfo\Network\ConnectPeer_List()\Port = *Info\Port If ListSize(G_ProgramMiscInfo\Network\ConnectPeer_ResiltID_List())<200 LastElement(G_ProgramMiscInfo\Network\ConnectPeer_ResiltID_List()) If AddElement(G_ProgramMiscInfo\Network\ConnectPeer_ResiltID_List()) G_ProgramMiscInfo\Network\ConnectPeer_ResiltID_List()\INFO_Hash = *Info\INFO_Hash G_ProgramMiscInfo\Network\ConnectPeer_ResiltID_List()\IP_Peer = *Info\IP_Peer G_ProgramMiscInfo\Network\ConnectPeer_ResiltID_List()\Port = *Info\Port G_ProgramMiscInfo\Network\ConnectPeer_ResiltID_List()\ConnectID = ConnectID x=#True EndIf EndIf DeleteElement(G_ProgramMiscInfo\Network\ConnectPeer_List()) Break EndIf EndIf Next If x=#False If ConnectID CloseNetworkConnection(ConnectID) ConnectID=0 EndIf EndIf UnlockMutex(G_ProgramMiscInfo\Network\ConnectPeer_Mutex) ProcedureReturn x EndProcedure Procedure Core_Network_ConnectPeer_Thread(*x) ; Поток установки связи с пирами. Protected Info.ProgramStatus_Network_ConnectPeer, ConnectID, x.b, BlockingMode Protected EventID.Integer, CurrentTime.l, Socket, Temp, CountTest Protected NetworkEvents.WSANETWORKEVENTS Protected WSACloseEvent.WSACloseEvent=G_ProgramMiscInfo\Network\WSA\WSACloseEvent Protected WSAEventSelect.WSAEventSelect=G_ProgramMiscInfo\Network\WSA\WSAEventSelect Protected WSAWaitForMultipleEvents.WSAWaitForMultipleEvents=G_ProgramMiscInfo\Network\WSA\WSAWaitForMultipleEvents Protected WSAEnumNetworkEvents.WSAEnumNetworkEvents=G_ProgramMiscInfo\Network\WSA\WSAEnumNetworkEvents Repeat If G_ProgramMiscInfo\ProgEndSate <> 0 ; Прога закрывается - завершить работу потока. Break EndIf LockMutex(G_ProgramMiscInfo\Network\ConnectPeer_Mutex) x=#False If ListSize(G_ProgramMiscInfo\Network\ConnectPeer_List())<=0 ; Список пуст. UnlockMutex(G_ProgramMiscInfo\Network\ConnectPeer_Mutex) Goto Core_Network_ConnectPeer_Thread_m2 ;Break EndIf ForEach G_ProgramMiscInfo\Network\ConnectPeer_List() If G_ProgramMiscInfo\Network\ConnectPeer_List()\Active = #True Continue EndIf Info\INFO_Hash = G_ProgramMiscInfo\Network\ConnectPeer_List()\INFO_Hash Info\IP_Peer = G_ProgramMiscInfo\Network\ConnectPeer_List()\IP_Peer Info\Port = G_ProgramMiscInfo\Network\ConnectPeer_List()\Port G_ProgramMiscInfo\Network\ConnectPeer_List()\Active = #True x=#True Break Next UnlockMutex(G_ProgramMiscInfo\Network\ConnectPeer_Mutex) If x=#True ConnectID=0 EventID\i=0 If Info\INFO_Hash<>"" And Info\IP_Peer<>"" And Info\Port>0 ConnectID=WSA_OpenNetworkConnection(Info\IP_Peer, Info\Port, @EventID) EndIf CurrentTime = G_ProgramMiscInfo\CurrentDate If ConnectID=0 Core_Network_ConnectPeer_SetResult(ConnectID, @Info) Else If ListSize(G_ProgramMiscInfo\Network\TestConnect())<1000 LastElement(G_ProgramMiscInfo\Network\TestConnect()) If AddElement(G_ProgramMiscInfo\Network\TestConnect()) G_ProgramMiscInfo\Network\TestConnect()\hEvent = EventID\i G_ProgramMiscInfo\Network\TestConnect()\ConnectID = ConnectID G_ProgramMiscInfo\Network\TestConnect()\INFO_Hash = Info\INFO_Hash G_ProgramMiscInfo\Network\TestConnect()\IP_Peer = Info\IP_Peer G_ProgramMiscInfo\Network\TestConnect()\Port = Info\Port G_ProgramMiscInfo\Network\TestConnect()\Time_Conn = CurrentTime Else Goto Core_Network_ConnectPeer_Thread_m1 EndIf Else ; Список переполнен! Core_Network_ConnectPeer_Thread_m1: CloseNetworkConnection(ConnectID) If EventID\i WSACloseEvent(EventID\i) EndIf EndIf EndIf Else Break EndIf ForEver Core_Network_ConnectPeer_Thread_m2: ForEach G_ProgramMiscInfo\Network\TestConnect() ; Проверяем установлен и конект с пиром (асинхронный сокет). x=#False BlockingMode=G_ProgramMiscInfo\Network\TestConnect()\hEvent Temp = WSAWaitForMultipleEvents(1, @BlockingMode, #False, 0, #False) ;1 If Temp <> #WSA_WAIT_FAILED ; Нет ошибки. If Temp <> #WSA_WAIT_TIMEOUT ; Выхогд не по таймауту. Socket=ConnectionID(G_ProgramMiscInfo\Network\TestConnect()\ConnectID) If WSAEnumNetworkEvents(Socket, BlockingMode, @NetworkEvents)<>#SOCKET_ERROR ; Нет ошибки. If NetworkEvents\lNetworkEvents & #FD_CONNECT If NetworkEvents\iErrorCode[#FD_CONNECT_BIT]=0 ; ОК, с пиром удалось установить конект. x=#True Else x=-1 EndIf EndIf Else ; Ошибка WSAEnumNetworkEvents(). x=-1 EndIf EndIf Else ; Ошибка WSAWaitForMultipleEvents(). x=-1 EndIf If x=#False ; Пока что с пиром нет соединения. If CurrentTime-G_ProgramMiscInfo\Network\TestConnect()\Time_Conn>=10 ; Прошло 10 или больше секунд с момента попытки установить связь ConnectID=G_ProgramMiscInfo\Network\TestConnect()\ConnectID Goto Core_Network_ConnectPeer_Thread_m3: ; Пира в топку. EndIf Else ; С пиром установлено соединение или произошла ошибка. ConnectID=G_ProgramMiscInfo\Network\TestConnect()\ConnectID If x=#True ; С пиром установлено соединение. Socket=ConnectionID(ConnectID) WSAEventSelect(Socket, 0, 0) Temp=0 ; Синхронный сокет. ioctlsocket_(Socket, #FIONBIO, @Temp) WSACloseEvent(G_ProgramMiscInfo\Network\TestConnect()\hEvent) Else ; Произошла ошибка Core_Network_ConnectPeer_Thread_m3: CloseNetworkConnection(ConnectID) G_ProgramMiscInfo\Network\TestConnect()\ConnectID=0 ConnectID=0 EndIf Info\INFO_Hash = G_ProgramMiscInfo\Network\TestConnect()\INFO_Hash Info\IP_Peer = G_ProgramMiscInfo\Network\TestConnect()\IP_Peer Info\Port = G_ProgramMiscInfo\Network\TestConnect()\Port Core_Network_ConnectPeer_SetResult(ConnectID, @Info) ; Запись в список, результата конекта с пиром. DeleteElement(G_ProgramMiscInfo\Network\TestConnect()) EndIf Next G_ProgramMiscInfo\Network\ConnectPeer_CountPeerConnect = ListSize(G_ProgramMiscInfo\Network\TestConnect()) EndProcedure Procedure Core_NetworkEvent_Thread(*x) ; Поток обработки событий сети, в т. ч. и сервера (для входящих соединений пиров). Protected SEvent, Server, ClientID, *Buffer Protected Size, PauseCount, OldCurrentDate.l, Sec Protected Max_PauseCount, TempL.l Protected Local_TorrentList.Core_Torrent ; Локальная копия структуры торрентов. Delay(200) For Size=0 To 7 *Buffer = AllocateMemory(70*1024) If *Buffer Break Else Delay(100) EndIf Next If *Buffer Peer_CopyInfo(@Local_TorrentList, 0) OldCurrentDate = G_ProgramMiscInfo\CurrentDate Repeat SEvent = NetworkServerEvent() If SEvent Server = EventServer() ClientID = EventClient() If Server = #TorrentServer Select SEvent ;Case #PB_NetworkEvent_Connect Case #PB_NetworkEvent_Disconnect Peer_ServerDisconnect(@Local_TorrentList, ClientID) Case #PB_NetworkEvent_Data FillMemory(*Buffer, 65536, 0) Size = ReceiveNetworkData(ClientID, *Buffer, 65536) If Size>0 And Size<=65536 Peer_ServerCore(ClientID, *Buffer, Size, @Local_TorrentList) EndIf EndSelect Else ; Это не сервер, а глюк. If SEvent = #PB_NetworkEvent_Data ReceiveNetworkData(ClientID, *Buffer, 65536) EndIf CloseNetworkConnection(ClientID) ; Разрываем связь. EndIf EndIf If PauseCount>Max_PauseCount : Max_PauseCount=PauseCount : EndIf If (Peer_Core(@Local_TorrentList, *Buffer)=#False And SEvent=0) Or PauseCount>=1000 If PauseCount>500 Delay(2) ElseIf PauseCount>200 Delay(10) Else Delay(20) EndIf PauseCount=0 Else PauseCount+1 EndIf TempL = G_ProgramMiscInfo\CurrentDate If OldCurrentDate <> TempL ; Прошла секунда. Local_TorrentList\Info\Current_Time = TempL Sec = TempL-OldCurrentDate Peer_CopyInfo(@Local_TorrentList, Max_PauseCount) ; Копирование данных из структуры торрантов в локальную структуру и обратно. If Sec>0 Peer_CountTimesPeer(Sec, @Local_TorrentList) ; Подсчет времени пиров для формирования keepalive запросов и закрытия соединения с клиентами, не присылающими запросы. EndIf Max_PauseCount=0 OldCurrentDate = TempL EndIf If G_ProgramMiscInfo\ProgEndSate <> 0 ; Прога закрывается - завершить работу потока. Break EndIf ForEver FreeMemory(*Buffer) Else G_ProgramMiscInfo\Thread\Network_ThreadID = 0 MessageRequester(#MessageName, "Ошибка Network-потока!", #MB_OK|#MB_ICONERROR) End EndIf EndProcedure Procedure Core_Times_Thread(*x) ; Поток подсчета времени. Protected GeneralCount, OldDate, Date, Sec Protected i, MiscInfo_ImageWidth.w, SizeCount.a Protected MiscInfo_ImageHeigh.w, SaveTimer OldDate = Date() GeneralCount = 0 SaveTimer = 0 For i=1 To 10 If AddSysTrayIcon(#SysTrayID, WindowID(#MainWin), ImageID(#MainWin_TrayIcon)) Break Else Delay(200) EndIf Next i G_ProgramMiscInfo\Thread\UpdateTracker_ThreadID = CreateThread(@Core_UpdateTracker_Thread(), 0) If G_ProgramMiscInfo\Thread\UpdateTracker_ThreadID = 0 MessageRequester(#MessageName, "Ошибка запуска потока"+Chr(10)+"обновления трекеров!", #MB_ICONERROR) End Else ThreadPriority(G_ProgramMiscInfo\Thread\UpdateTracker_ThreadID, 8) EndIf G_ProgramMiscInfo\Thread\DomainsPeer_ThreadID = CreateThread(@Core_DomainsPeer_Thread(), 0) If G_ProgramMiscInfo\Thread\DomainsPeer_ThreadID = 0 MessageRequester(#MessageName, "Ошибка запуска потока"+Chr(10)+"сбора информации о пирах!", #MB_ICONERROR) End Else ThreadPriority(G_ProgramMiscInfo\Thread\DomainsPeer_ThreadID, 8) EndIf Repeat If SizeCount>=10 If TrySemaphore(G_ProgramMiscInfo\Panel_Info_Semaphore) OutText_Core(1) TabControl_SelectTab() EndIf SizeCount=0 EndIf SizeCount+1 If MiscInfo_ImageWidth<>G_ProgramMiscInfo\Panel_Info_MiscInfo_ImageWidth Or MiscInfo_ImageHeigh<>G_ProgramMiscInfo\Panel_Info_MiscInfo_ImageHeight If G_ProgramMiscInfo\Panel_Info_Page=5 Or MiscInfo_ImageHeigh=G_ProgramMiscInfo\Panel_Info_MiscInfo_ImageHeight OutText_Core(2) EndIf MiscInfo_ImageWidth=G_ProgramMiscInfo\Panel_Info_MiscInfo_ImageWidth MiscInfo_ImageHeigh=G_ProgramMiscInfo\Panel_Info_MiscInfo_ImageHeight EndIf If GeneralCount>=10 ; Прошло примерно 320 миллисекунд GeneralCount = 0 Date = Date() If OldDate<>Date Sec = Date-OldDate If Sec>0 Torrent_CountTimes(Sec) ; Подсчет времени в торрентах. Tracker_CountTimes(Sec) ; Подсчет времени до обновления информации с трекера и постановка в серверов в очередь обновления. OutText_Update_Speed() ; Обновление данных о скорости. OutText_Core(0) ; Вывод данных на панель информации. Out_Tray() ; Вывод подстазки в трее. Out_StatusBar() ; Вывод даных в строку состояния. SaveTimer+1 If SaveTimer>=120 ; Прошло 2 минуты. SaveTimer=0 If SaveTorrentData() = #False ; Сохранениеинвы о торрентах AddGadgetItem(#MainWin_Panel_Info_ListIcon_Log, -1, TimeLog()+"Ошибка сохранения конфигурации торрентов.", ImageID(#MainWin_Panel_Info_Icon_Log_Warning)) SaveTimer=100 EndIf EndIf G_ProgramMiscInfo\CurrentDate = Date EndIf OldDate=Date EndIf EndIf GeneralCount+1 If G_ProgramMiscInfo\ProgEndSate <> 0 ; Прога закрывается - завершить работу потока. Break EndIf Delay(2) ForEver EndProcedure DisableExplicit ; IDE Options = PureBasic 5.11 (Windows - x86) ; CursorPosition = 1 ; Folding = -- ; EnableXP