Has anyone used this? I was wondering whether to use this or a new thread for reading a file.
For example, a text or hex viewer, all you need is the first bit of a file, the rest can be processed in the background.
Both methods would be able to interact with the user, but is one better than the other?
Quote from: sinsi on February 12, 2010, 10:19:41 AM
Has anyone used this? I was wondering whether to use this or a new thread for reading a file.
For example, a text or hex viewer, all you need is the first bit of a file, the rest can be processed in the background.
Both methods would be able to interact with the user, but is one better than the other?
I dont think multithreading will make the hardisk read speed faster, it does not affecting it. Except off course, the harddisk reader iron is more than one.
I'm not worried about the speed of reading, just the ability to e.g. click on 'cancel' instead of the ReadFile blocking.
Asynchronous I/O generally gives better performance and scales better, but multi-threading is much simplier to use. In the case of a simple text file, I would go with a seperate thread; if you are not "doing" anything else, and just want control over the GUI for the users sake, there's no reason to get involved with alertable wait states and all that.
-r
Quote from: redskullbut multi-threading is much simplier to use
Funny, I thought that was harder...not having any experience with threads that's not suprising eh?
I figure that windows will do its own optimising with an async call, does that negate having a thread do it?
Like I say, speed is not an issue - I just hate it when a program ignores my clicks. "Cancel you f*cker!!!!!!"
threads are easy :P
even I can get a thread going
after that, i am lost - lol
just make the file-read thread keep track of the file pointer so your main program knows how much of the file has been read
that means you need a little handshaking so they don't try to access the pointer at the same time
Quote from: daveeven I can get a thread going
Alright, I am on my way!
Quote from: sinsi on February 12, 2010, 01:19:58 PM
Funny, I thought that was harder...not having any experience with threads that's not suprising eh?
To each his own; i guess whichever one you have more experience with would be the one to choose. The main benefit of AIO is for when you have lots of IO calls to do (like, in the hundreds); if you have a single thread with blocking calls, you can't do the next one until the first one is done. If you have a seperate thread for each one, you load down the system with more threads than it can handle. With overlapped I/O, you get the best of both worlds.
-r
it is easy
write a proc like you would any other
replace the RET with ExitThread
instead of invoke'ing the proc, use CreateThread
if you want to use the same thread code for multiple threads, you can use GetThreadID
and use that value to index into a data array so each thread has it's own data
Thanks, Dave - that was really a cute cookbook :U
Here is my translation:
include \masm32\include\masm32rt.inc
MyThread PROTO: DWORD
.data?
hThread dd ?
TheFlag dd ?
ThreadID dd ?
ExitCode dd ?
.code
start: ; invoke Sleep, 0 ; sometimes this was needed, no idea why
invoke CreateThread, 0, 0, offset MyThread, 123, 0, offset ThreadID
mov hThread, eax
print str$(eax), 9, " is the thread handle", 13, 10
.Repeat
invoke Sleep, 50
print "*"
.Until rv(GetExitCodeThread, hThread, offset ExitCode)==0 || ExitCode!=STILL_ACTIVE
print chr$(13, 10)
print str$(TheFlag), 9, " is the value that MyThread moved into TheFlag", 13, 10
print str$(ExitCode), 9, " is the ExitCode returned by MyThread", 13, 10
print str$(ThreadID), 9, " is the ThreadID", 13, 10
getkey
exit
MyThread proc singleArg:DWORD
invoke Sleep, 600
mov TheFlag, 321
invoke ExitThread, singleArg
MyThread endp
end start
i was thinking something like this...
.data
ThreadIndexTable dw 8 dup(0)
.data?
ThreadDataArray dw 64 dup(?) ;8 threads - 8 dwords each thread
.code
start:
;create 8 threads using the same routine
invoke ExitProcess
ThreadCode PROC
invoke GetThreadID
;find an empty entry in ThreadIndexTable to place the thread ID
;from the position in ThreadIndexTable, calculate the index into ThreadDataArray
;now each thread has 8 dwords of data, unique from the other threads using the same code
;
;
;
invoke ExitThread
ThreadCode ENDP
END start
depending on how the OS hands out thread ID's, you may not need the ThreadIndexTable
ExitThread is not really needed - eax+ret does the same.
Quote from: qWord on February 12, 2010, 06:34:22 PM
ExitThread is not really needed - eax+ret does the same.
MSDN is a bit cloudy about what really happens (http://msdn.microsoft.com/en-us/library/ms682659%28VS.85%29.aspx):
QuoteExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.
When this function is called (either explicitly or by returning from a thread procedure), the current thread's stack is deallocated, all pending I/O initiated by the thread is canceled, and the thread terminates. The entry-point function of all attached dynamic-link libraries (DLLs) is invoked with a value indicating that the thread is detaching from the DLL.
QuoteWhen this function is called (either explicitly or by returning from a thread procedure)...
IMO its clear: there is no differenc between ExitThread and RET. Using OllyDbg you can see that both methods end up in a call to
RtlExitUserThread (ntdll).
I think we should follow the preferred advice for C and not C++ :green
Whether you call RET or ExitThread, the same thing happens (the thread is ended). The problem for C++ is that destructors are automatically added *at the end* (after the ExitThread call); you code ends up doing this:
;Do Stuff
CALL ExitThread ---> Ends the thread
CALL DestructorFunction ---> Never called!
It's not really applicable to asm (or C), or even C++ unless you have OS things reserved (handles, semaphore, objects). You can sometimes dupe the compiler by putting braces around the class:
MyThread() {
{
MyClass MyObj
Do Stuff
} <-- Generates call to desctructor
ExitThread()
-r
Quote from: qWord on February 12, 2010, 07:17:40 PM
QuoteWhen this function is called (either explicitly or by returning from a thread procedure)...
IMO its clear: there is no differenc between ExitThread and RET. Using OllyDbg you can see that both methods end up in a call to
RtlExitUserThread (ntdll).
Actually, Olly 1.1 gets stuck in the thread, but I could convince Olly 2. This is what I found, confirming more or less what you write:
QuoteMyThread proc singleArg:DWORD
invoke Sleep, 1000
mov TheFlag, 321
return singleArg
; instead of invoke ExitThread, singleArg; translates into:
mov eax, singleArg
leave
retn 4 ; 40110A
; ...
push eax ; 7C80B683
call ExitThread
MyThread endp
So a simple
ret does indeed the same job.
Quote from: jj2007 on February 12, 2010, 11:00:28 PMActually, Olly 1.1 gets stuck in the thread
I've had the same problems until some on told me that this problem is caused by the plugin
(which injects code in the debugged process) for decoding SSE-registers -> disable
options->registers->'decode SSE registers'.
qword
Quote from: jj2007 on February 12, 2010, 05:54:50 PM
invoke CreateThread, 0, 0, offset MyThread, 123, 0, offset ThreadID
When I used to code in VC *shudder* I seem to remember I used to pass an address as the thread value (123), I see Dave creates a global var to hold extra data.... I think my way is better but I'm open to you guys criticising my methology in the pursuit of truth....
mov esi, alloc(32)
mov [esi+X], Data You Want To Pass (<---- You might find this syntax errors :D)
invoke CreateThread, 0, 0, offset MyThread, esi, 0, offset ThreadID
No real difference I can see except readability, filesize, locality?