i was trying to do a little splashscreen so my program could open querys withaout blocking my aplication.
The code i wrote is this.
procedure TOpenThread.OpenTable;
begin
FActiveTable.NonBlocking := true;
FActiveTable.open;
end;
procedure TOpenThread.AbrirTablas;
begin
FActiveTable := FOwnerPlan.TablasEdicion.Tabla;
Synchronize(OpenTable);
while FActiveTable.Executing do
begin
if Terminated then CancelExecution;
sleep(10);
end;
FActiveTable.NonBlocking := false;
end;
This code is executing in a thread, and keeps doing it while the main thread gets stucked
I'm using delphi 2007
This code is executing in a thread
Now, it does not. Your code is:
Synchronize(OpenTable);
This explicitly means OpenTable procedure is executed within Main VCL thread and outside of your background auxillary TOpenThread.
More details on Synchronize that you may try to learn from are at https://stackoverflow.com/a/44162039/976391
All in all, there is just no simple solutions to complex problems.
If you want to offload DB interactions into a separate thread, you would have to make that thread exclusive owner and user of all DB components starting from the very DB connection and up to every transaction and every query.
Then you would have to make means to ASYNCHRONOUSLY post data requests from Main VCL Thread to the DB helper thread, and ASYNCHRONOUSLY receive data packets from it. Something like OmniThreadLibrary does with data streams - read their tutorials to get a gist of internal program structure when using multithreading.
You may TRY to modify your application to the following rules of thumb.
It would not be the fastest multithreading, but maybe the easiest.
all database components work is exclusively done inside TOpenThread.Execute context and those components are local members variables to the TOpenThread class. The connection-disconnection made only within TOpenThread.Execute; TOpenThread.Execute waits for the commands from the main thread in the almost infinite (until the thread gets terminated) and throttled loop.
specific database requests are made as anonymous procedures and are added to some TThreadedQueue<T> public member of TOpenThread object. The loop inside .Execute tries to fetch the action from that queue and execute it, if any exists, or throttle (Yield()) if the queue was empty. Neither Synchronize nor Queue wrappers are allowed around database operations. Main VCL thread only posts the requests, but NEVER waits for them to be actually executed.
those anonymous procedures after being executed do pass the database results back into main thread. Like http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/ or like Sending data from TThread to main VCL Thread or by any other back-into-main-thread way.
TOpenThread.Execute only exits the loop if the Terminated flag is set and the queue is empty. If Terminated is set then immediate exit would loose the actions still waiting on queue unprocessed.
Seems boring and tedious but easy? Not at all, add there that you would have to intercept exceptions and process all the errors in the async way - and you would "loose any hope entering this realm".
PS. and last but not least, about "This code is executing in a thread, and keeps doing it while the main thread gets stucked" supposition, frankly, I guess that you are wrong here and i think that BOTH your threads are stuck by one another.
Without fully understanding how thread-to-thread locking is designed to work in this specific component, carpet-bombing code with calls to Synchronize and other inter-thread locking tools, you have quite a chance to just chase them all your threads into the state of mutual lock, deadlock. See http://stackoverflow.com/questions/34512/
Related
I remember there was a way to do this, something similar to unix signals, but not so widely used. But can't remember the term. No events/mutexes are used: the thread is just interrupted at random place, the function is called and when it returns, the thread continues.
Windows has Asynchronous Procedure Calls which can call a function in the context of a specific thread. APC's do not just interrupt a thread at a random place (that would be dangerous - the thread could be in the middle of writing to a file or obtaining a lock or in Kernel mode). Instead an APC will be dispatched when the calling thread enters an alterable wait by calling a specific function (See the APC documentation).
If the reason that you need to call code in a specific thread is because you are interacting with the user interface, it would be more direct to send or post a window message to the window handle that you want to update. Window messages are always processed in the thread that created the window.
you can search RtlRemoteCall, it's an undocumented routine though. there's APC in Windows semantically similar to Unix signal, however APC requires target thread is in an alertable state to get delivered, it's not guaranteed this condition is always met
I currently have a program running with about 20 threads at a time. I am fairly new to multi-threading so I'm a little confused on proper data protection.
Currently, my threads use Events as data locks an unlocks. I opted to use this over critical sections as most data is only shared between two or three threads so preventing a single thread from reading while one wrote by stopping all 20 threads seemed wasteful. I used Event over Mutex simply due to the fact that I could not (easily) find a source that clearly explained how a Mutex works and how to implement one.
I'm using Win32 API for my multi-threading. In my current setup I use Events to lock data so my event would be something like "DataUnlock" When not set I know that the data is being worked on. When set I know it is ok to work on the data. So my makeshift data locks look something like this.
WaitForSingleObject( DataUnlock,INFINITE ); //Wait until the Data is free
ResetEvent(DataUnlock); //Signal that the data is being worked on
...work on Data...
SetEvent(DataUnlock); //Signal that the data is free to use
My first question is: Is this as good (efficient) as using a Mutex when only two threads are accessing the data?
Second: If more than two threads waiting to access the data is there a potential that both will be triggered when the data is freed (will the both pass the wait before one reaches ResetEvent)? If so, would a mutex have the same issue?
Lastly: If a mutex is preferable, how would I go about implementing one (a link or explanation would be greatly appreciated)?
Thanks!
I don't think that the event approach is the best way of protecting the data.
Look at Mutex Objects and Using Mutex Objects to learn about mutexes.
One of your threads has to create a mutex. The CreateMutex function returns a handle to the mutex object. You can pass the handle as an argument to the threads dealing with your data.
Use the WaitForSingleObject function to wait for the mutex and then process your data. Release the mutex with a call to the ReleaseMutex function. When a mutex is released the next wait function will gain the mutex.
In case the data is to be accessed by threads of multiple processes, named mutexes have to be used.
Look at Critical Section Objects to learn about critical section synchronisation.
If you want to have the
A critical section has to be created by a call to the InitializeCriticalSection function.
Use the EnterCriticalSection function at all places before you handle your data.
The LeaveCriticalSection function releases the critical section releases the object. Use this call after you're done with the data.
The critical section can only be entered by the owning thread. Once a thread has gained the critical section object, no other thread can get access to your data. Other threads will block at the call to EnterCriticalSection(). However the thread owns the critical section can do succesive calls to EnterCriticalSection() more than once. Care shall be taken to call LeaveCriticalSection() once for every call to EnterCriticalSection().
Your example would let all threads waiting for the event process your data. And you would only know by the data themself if processing of anykind has happened. That's up to you,
how to determine what was done and what still needs to be done. If you have many threads waiting for your event, you can't tell the order in which the get access.
I would recommend using a critical section object. It is lightweight and relatively easy to use. See Using Critical Section Objects for an example how to use critical section objects.
I'm trying to create a Child Process with Redirected Input and Output (as described here - http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx).
For the people that don't want to bother reading the source code on that page, the author is using anonymous pipes to redirect the child's input and output. The parent process writes to the child process's input and reads from the child process's output.
In that code however, the program is closing the pipes after reading and writing (in WriteToPipe and ReadFromPipe), so actually the program just reads a file, dumps it on the child process input stream and then reads the child process response.
Now, what I'm looking for is a code where we will not close the pipes, but we will continuously post requests and read the child process response (in contrast to making just 1 request).
I've tried several modifications to the source code given on the link posted above, but no matter what I try, the program always hangs when calling ReadFile() in the ReadFromPipe() function (it probably waits for the child to quit - but as I said I like to get the child response, and then send other requests to it).
Any ideas on how I can get over this?
Update:
Can anyone at least tell me whether using the .NET Process class with RedirectStandardInput and RedirectStandardOutput is a good option?
Had exactly the same problem, and solved it by using PeekNamedPipe (which according to MSDN is also fine for anonymous read pipes) to check for available data before each call to ReadFile. That removed the blocking issues I was getting, and allowed my GetExitCodeProcess() to see that the process had exited and cleanup the pipes.
Yes - the .Net Process class redirects the standard input / output of the child process with anonymous pipes in a very similar way to the linked sample if you use RedirectStandardInput and RedirectStandardOutput, so this is probably a fairly good option.
As for why ReadFile is hanging - it sounds like this function is waiting for the child process to either send some data back, or to close the pipe. If you want to continuously post requests to the child process then you need to either:
Know exactly when it is appropriate to read so that you are not left waiting / blocked for the child process (so for example you only read immediately after a request has been sent). This strategy is very risky as there is always a chance that the child process doesn't behave as expected and you are left waiting on the child process indefinitely.
Have a dedicated thread for reading - if you have a dedicated thread for reading then it doesn't matter that the thread may wait indefinitely for the child process as your other threads are still able to send requests and operate as normal. This method is more complex than the first option, however when done properly is far more robust. The only other drawback to this approach is that it requires you have an additional read thread for each child process, meaning that it doesn't scale very well if you need to communicate with a large number of child processes.
Use asynchronous IO - It is possible to call the ReadFile function in a way such that it always immediately returns, however notifies you when a read has completed (I'm a little fuzzy on the exact details on how this works as I'm more used to C#). This is know as Asynchronous IO and is the most versatile of these 3 methods as it allows you to communicate with many child processes without needing a dedicated thread for each one. The tradeoff however is that it is also the most complex to do correctly (at least in my opinion).
I've created two threads A & B using CreateThread windows API. I'm trying to send the data from thread A to B.
I know I can use Event object and wait for the Event object in another using "WaitForSingleObject" method. What this event does all is just signal the thread. That's it! But how I can send a data. Also I don't want thread B to wait till thread A signals. It has it own job to do. I can't make it wait.
I can't find a Windows function that will allow me to send data to / from the worker thread and main thread referencing the worker thread either by thread ID or by the returned HANDLE. I do not want to introduce the MFC dependency in my project and would like to hear any suggestions as to how others would or have done in this situation. Thanks in advance for any help!
First of all, you should keep in mind that Windows provides a number of mechanisms to deal with threading for you: I/O Completion Ports, old thread pools and new thread pools. Depending on what you're doing any of them might be useful for your purposes.
As to "sending" data from one thread to another, you have a couple of choices. Windows message queues are thread-safe, and a a thread (even if it doesn't have a window) can have a message queue, which you can post messages to using PostThreadMessage.
I've also posted code for a thread-safe queue in another answer.
As far as having the thread continue executing, but take note when a change has happened, the typical method is to have it call WaitForSingleObject with a timeout value of 0, then check the return value -- if it's WAIT_OBJECT_0, the Event (or whatever) has been set, so it needs to take note of the change. If it's WAIT_TIMEOUT, there's been no change, and it can continue executing. Either way, WaitForSingleObject returns immediately.
Since the two threads are in the same process (at least that's what it sounds like), then it is not necessary to "send" data. They can share it (e.g., a simple global variable). You do need to synchronize access to it via either an event, semaphore, mutex, etc.
Depending on what you are doing, it can be very simple.
Thread1Func() {
Set some global data
Signal semaphore to indicate it is available
}
Thread2Func() {
WaitForSingleObject to check/wait if data is available
use the data
}
If you are concerned with minimizing Windows dependencies, and assuming you are coding in C++, then I recommend using Boost.Threads, which is a pretty nice, Posix-like C++ threading interface. This will give you easy portability between Windows and Linux.
If you go this route, then use a mutex to protect any data shared across threads, and a condition variable (combined with the mutex) to signal one thread from the other.
DonĀ“t use a mutexes when only working in one single process, beacuse it has more overhead (since it is a system-wide defined object)... Place a critical section around Your data and try to enter it (as Jerry Coffin did in his code around for the thread safe queue).
I wish to launch a separate thread for handling window messages (via a blocking GetMessage loop), but still create the windows in the initial thread, afterward.
Within the separate thread, as soon as it launches, I am calling PeekMessage with PM_NOREMOVE to ensure a message queue exists (is this necessary?), followed by..
AttachThreadInput(initial thread id,GetCurrentThreadId(),true)
..before finally entering the message loop
I am not yet using a mutex or cs to ensure this is happening in time, but am merely using a Sleep statement in my initial thread for the sake of simplicity.
Regardless, window messages do not appear to be intercepted by the separate thread.
I am a little unsure as to whether I am doing this correctly, and would appreciate any possible guidance. Both threads are in the same process
Thank you all
That's not what AttachThreadInput does. Even after you attach your input queue to another thread, Windows still have thread affinity. Messages in the queue for a given window can only be removed from the queue by that window's thread.
What AttachTheadInput does is to make two threads share an input queue. This allows them to query information about the input state and know that the other thread will get the same answer for the same query. For instance, one thread could call GetAsyncKeyState and know that the answer reflected the key state for the other thread.
It allows two or more threads to have the same relationship to the input queue and each other as processes had in Windows 3x. This is the reason that this API exists; so that complex multiprocess applications could be ported from Win 3x to Win95/WinNT.
It seems the best way to instigate window creation from the main thread, while having messages for them handled in a separate, looping thread is to use a custom message, that can be sent to the separate thread - Thus allowing it to create the window, but still allowing that action to be invoked from the initial thread:
1) Allocate a custom message, and create a structure to hold the window initialisation parameters:
message_create_window = WM_USER + 0;
class Message_create_window{
Message_create_window(...);
};
2) Instead of calling CreateWindow(Ex), use something similiar to the following, passing in the relavant window creation parameters:
PostThreadMessage(
thread.id,
message_create_window,
new Message_create_window(...),
0
);
3) Handle the custom message in the message pump of your ui handling thread, extract the creation parameters, & free afterwards:
MSG msg;
GetMessage(&msg,0,0,0);
...
switch(msg->message){
...
case message_create_window:{
Message_create_window *data=msg->wParam;
CreateWindowEx(data->...);
delete data;
}break;
...
This does, however, have the following side-effects:
The window will be created asynchronously. If it is required that the initial thread block until the window is created (or, indeed, that the window's existence can ever be asserted) then a thread synchronisation tool must be used (such as an event)
Care should be taken when interacting with the window (it is a multithreaded application, after all)
If there are any major holes in this answer, or this seems like a terrible approach, please correct me.
(This is still my question, & I am trying to find the best way to accomplish this)