How can I read an .ini file in a thread without consuming so much CPU time? The thread will run at runtime, this means while true without delay.
The code to search the value on .ini is:
var
Leitura : TIniFile;
begin
Result := False;
Leitura := TIniFile.Create('File.ini');
if Leitura.ValueExists('KEY', ValueToSearch) then Result := True;
Leitura.Free;
but since this function runs in an infinite loop, it consumes CPU time, and I need solve this question.
Instead of continuously polling the .INI file for changes you could monitor the file for changes using the FindFirstChangeNotification API and only check the value when the file has changed. Earlier Delphi versions contained a component TShellChangeNotifier in the unit ShellCtrls.pas which was a wrapper around the API function. There is furthermore an article A Directory Monitor Class For Delphi that shows how to use the ReadDirectoryChangesW Windows API function. ReadDirectoryChangesW "retrieves information that describes the changes within the specified directory". The Delphi JCL contains a component TJvChangeNotify to monitor file and directory changes, too. On Torry you can finally find a component ATFileNotification that allows to watch for file/directories changes and to fire an event when change occurs.
Related
Sometimes it happens, that some files of my application are used by some processes. For example, user opens application log, or something like that, and forgets to close it. This causes some errors while installing/upgrading/uninstalling. In such cases, I'd like to find out, what process is using file, and show user a message, indicating, that files are used.
Is it possible in Inno Setup to find out, what process prevents script from modifying file? At least, when I'm trying to do this in Code section.
The Inno Setup can automatically check, if the installed files are locked by some processes, and offer a user to close (and restart later) the applications automatically (since 5.5.0).
Make sure the CloseApplications directive is set to its default value yes.
Though by default, only *.exe,*.dll,*.chm files are checked. If you want to check also other or all other files, modify the CloseApplicationsFilter directive:
[Setup]
; default
CloseApplications=yes
; check all files
CloseApplicationsFilter=*.*
If you are installing some files by a code, use the RegisterExtraCloseApplicationsResources event function:
procedure RegisterExtraCloseApplicationsResources;
begin
RegisterExtraCloseApplicationsResource(
False, ExpandConstant('{userappdata}\My Program.log'));
end;
I'm developping a multithreaded download application, the download works fine unless when I download a zip file: the content is downloaded but when I try to extract it I get : unexpected end of archive, I'm using winrar. But the problem is relevant to the app itself, more precisely the multithreaded download, (when I use one thread I don't get this error).
Well here is the relevant part of code:
//Main thread Creates worker threads and starts them
for I := 1 to ThreadCount do
begin
workerThreads[i]:=TWorkerThread.Create(URL,mapFile,PosBegin,size);
PosBegin:= PosBegin + size;
end;
//Code of worker thread:
HTTP.Request.Range := Format('%d-%d',[posBegin, posBegin + size -1]);
HTTP.Get(URL,ms);
data := MapViewOfFile(mapFile, FILE_MAP_WRITE, 0 ,0, size);
copymemory(data,ms.memory,ms.size);
What's the problem in my code?
Thanks dor your replies.
Your call to MapViewOfFile() is setting the dwFileOffsetHigh and dwFileOffsetLow parameters to 0, so every thread is writing its data to the same file offset 0, thus overwriting each other. You need to set the view's file offset to posBegin instead.
Also, if you are not already doing so, make sure you have pre-allocated the file to the total file size being downloaded by all threads, and have created a file mapping of that same size.
Appropriate code provided below. I had this working once but have since messed up due to having to change some of the other code. Can't figure out what I've done. The encrypt function creates a thread and makes a call to function EncryptProc to process one or more files. Once each file is completed it should print the name to a textctrl. In the codes current state it waits until all threads/files are processed before printing. It then prints evrything in one go. During processing the textctrl also completely disappears. Any help would be much appreciated as its starting to drive me nuts, lol.
---EDIT---
CODE REMOVED
There should be no GUI access from within threads - in your case EncryptProc is writing to the text control directly - you need to either:
Use CallAfter in the thread to update the text control after the thread exits or
Raise custom event an event in the thread that carries the file name information
and have a hander in the main thread that updates the text control
on receiving the event.
I have an MFC App which fires up a separate thread for downloading some files via cURL. At the start it downloads a text file with file sizes and last write times. Then it checks the files on disk and queues it for downloading if it has different values.. The problem is; the CreateFile call in the thread arbitrarily returns INVALID_HANDLE_VALUE. I always do CloseHandle() after a successful CreateFile(). The failing files are just random. Sometimes a file in the root dir, another time a file in a nested directory. The problem is not related to localization or directory/file names since sometimes all checks pass but sometimes don't. GetLastError() return 2 or 3 on occasion which are "File not found" / "Path not found" respectively.
When I put the function checking the file write times and size straight into the OnInitDialog() function, everything works. This smells like a multithreading issue but I double-checked everything from memory allocations to file handles.
The same code works in a console application also in a separate thread.
The platform is Win7 64bit.
Linking statically to the runtime and MFC.
in my case GetCurrentDirectory() returned the system32 path after some time so my code failed because of credentials. I fixed the issue by determining file paths manually (getting the exe path at the start and use it from there on...) . Make sure you are not trying to write to/read from a privileged location on disk. Check your paths.
I am working on VC++ project, in that my application process a file from input path and generates 3 output "*.DAT" files in the destination path. I will FTP these DAT file to the destination server. After FTP, I need to delete only two output .DAT files the folder. I am able to delete those files, because there one Asynchronous thread running behind the process. Since the thread is running, while deleting it says, "Cannot delete, the file is used by another person".
I need to stop that thread and delete the files. Multiple files can also be taken from the input path to process.
Please help me in resolving this issue. Its very high priority issue for me. Please help me ASAP.
I don't think this is a threading issue. Instead I think your problem is that Windows won't let you delete a file that still has open handles referencing it. Make sure that you call CloseHandle on handles to the file that you want to delete first. Also ensure that whatever mechanism you are using to perform the FTP transfer doesn't have any handles open to the file you want to delete.
I don't think that forcing the background thread down will solve your problem. You can't delete the files because you're holding an open handle to those files. You must close the handle first. Create an event object and share it between your main thread and the background thread. When the background thread is done sending the files through FTP, it should set this event. Have your main thread wait on the event before deleting the files.
Background Thread:
SendFiles();
ReleaseResources(); // (might be necessary, depending on your design)
SetEvent( hFilesSentEvent );
Main Thread:
WaitForSingleObject( hFilesSentEvent );
DeleteFiles();