IOmniTaskControl.Unobserved - the task is never destroyed - multithreading

I am trying to run a fire-and-forget task - IOmniTaskControl.Unobserved works well enough with either IOmniTaskControl.Run or IOmniTaskControl.Schedule(IOmniThreadPool), but the IOmniTaskControl object is never destroyed.
I am limited to using Unobserved since I have an arbitrary number of tasks and I do not want to store them in a dedicated variable or a list - removing a task from that list would be a hustle in itself since it can only be done from the task body.
Am I missing something? I thought that IOmniTaskControl.Unobserved will destroy itself after it runs.

I think I've never answered my own question that quickly :-)
TOmniTaskControl is destructed from the TOmniEventMonitor.WndProc window proc, which of course only runs if there is a message loop in the thread where the monitor was created by the task. In my case, the tasks were created from a dedicated thread (I used TThread.CreateAnonymousThread). Adding a message loop to my thread proc (which runs an infinite while loop) fixed the problem:
//Omni thread library uses Windows messages to communicate with itself
while PeekMessage(wMsg, 0, 0, 0, PM_REMOVE or PM_NOYIELD) do begin
TranslateMessage(wMsg);
DispatchMessage(wMsg)
end;

Related

How to sync Delphi event while running DB operations in a background thread?

Using Delphi 7 & UIB, I'm running database operations in a background thread to eliminate problems like:
Timeout
Priority
Immediate Force-reconnect after network-loss
Non-blocked UI
Keeping an opened DB connection alive
User canceling
I've read ALL related topics here, and realized: using while isMyThreadStillRuning and not UserCanceled do sleep(100); end; isn't the recommended way to do this, but rather using TEvent.WaitFor(3000)....
The solutions here are either about sending signals FROM or TO... the thread, or doing it with messages, but never both ways.
Reading the help file, I've also found TSimpleEvent, which seems to be easier to use.
So what is the recommended way to communicate between Main-UI + DB-Thread in both ways?
Should I simply create 2+2 TSimpleEvent?
to start a new transaction (thread should stop sleeping)
force-STOP execution
to signal back if it's moved to a new stage (transaction started / executed / commited=done)
to signal back if there is any error happened
or should there be only 1 TEvent?
Update 2:
First tests show:
2x TSimpleEvent is enough (1 for Thread + 1 for Gui)
Both created as public properties of the background thread
Force-terminating the thread does not work. (Too many errors impossible to handle..)
Better to set a variable like (Stop_yourself) and let it cancel and free itself, (while creating a new instance from the same class and try again.)
(still work in progress...)
You should move the query to a TThread. Unfortunately, anonymous threads are not available in D7 so you need to write your own TThread derived class. Inside, you need its own DB connection to prevent shared resources. From the caller method, you can wait for the thread to end. The results should be stored somewhere in the caller class. Ensure that the access to parameters of the query and for storing the result of the query is handled thread-safe by using a TMutex or TMonitor.

thread with a forever loop with one inherently asynch operation

I'm trying to understand the semantics of async/await in an infinitely looping worker thread started inside a windows service. I'm a newbie at this so give me some leeway here, I'm trying to understand the concept.
The worker thread will loop forever (until the service is stopped) and it processes an external queue resource (in this case a SQL Server Service Broker queue).
The worker thread uses config data which could be changed while the service is running by receiving commands on the main service thread via some kind of IPC. Ideally the worker thread should process those config changes while waiting for the external queue messages to be received. Reading from service broker is inherently asynchronous, you literally issue a "waitfor receive" TSQL statement with a receive timeout.
But I don't quite understand the flow of control I'd need to use to do that.
Let's say I used a concurrentQueue to pass config change messages from the main thread to the worker thread. Then, if I did something like...
void ProcessBrokerMessages() {
foreach (BrokerMessage m in ReadBrokerQueue()) {
ProcessMessage(m);
}
}
// ... inside the worker thread:
while (!serviceStopped) {
foreach (configChange in configChangeConcurrentQueue) {
processConfigChange(configChange);
}
ProcessBrokerMessages();
}
...then the foreach loop to process config changes and the broker processing function need to "take turns" to run. Specifically, the config-change-processing loop won't run while the potentially-long-running broker receive command is running.
My understanding is that simply turning the ProcessBrokerMessages() into an async method doesn't help me in this case (or I don't understand what will happen). To me, with my lack of understanding, the most intuitive interpretation seems to be that when I hit the async call it would go off and do its thing, and execution would continue with a restart of the outer while loop... but that would mean the loop would also execute the ProcessBrokerMessages() function over and over even though it's already running from the invocation in the previous loop, which I don't want.
As far as I know this is not what would happen, though I only "know" that because I've read something along those lines. I don't really understand it.
Arguably the existing flow of control (ie, without the async call) is OK... if config changes affect ProcessBrokerMessages() function (which they can) then the config can't be changed while the function is running anyway. But that seems like it's a point specific to this particular example. I can imagine a case where config changes are changing something else that the thread does, unrelated to the ProcessBrokerMessages() call.
Can someone improve my understanding here? What's the right way to have
a block of code which loops over multiple statements
where one (or some) but not all of those statements are asynchronous
and the async operation should only ever be executing once at a time
but execution should keep looping through the rest of the statements while the single instance of the async operation runs
and the async method should be called again in the loop if the previous invocation has completed
It seems like I could use a BackgroundWorker to run the receive statement, which flips a flag when its job is done, but it also seems weird to me to create a thread specifically for processing the external resource and then, within that thread, create a BackgroundWorker to actually do that job.
You could use a CancelationToken. Most async functions accept one as a parameter, and they cancel the call (the returned Task actually) if the token is signaled. SqlCommand.ExecuteReaderAsync (which you're likely using to issue the WAITFOR RECEIVE is no different. So:
Have a cancellation token passed to the 'execution' thread.
The settings monitor (the one responding to IPC) also has a reference to the token
When a config change occurs, the monitoring makes the config change and then signals the token
the execution thread aborts any pending WAITFOR (or any pending processing in the message processing loop actually, you should use the cancellation token everywhere). any transaction is aborted and rolled back
restart the execution thread, with new cancellation token. It will use the new config
So in this particular case I decided to go with a simpler shared state solution. This is of course a less sound solution in principle, but since there's not a lot of shared state involved, and since the overall application isn't very complicated, it seemed forgivable.
My implementation here is to use locking, but have writes to the config from the service main thread wrapped up in a Task.Run(). The reader doesn't bother with a Task since the reader is already in its own thread.

Is the first thread that gets to run inside a Win32 process the "primary thread"? Need to understand the semantics

I create a process using CreateProcess() with the CREATE_SUSPENDED and then go ahead to create a little patch of code inside the remote process to load a DLL and call a function (exported by that DLL), using VirtualAllocEx() (with ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE), WriteProcessMemory(), then call FlushInstructionCache() on that patch of memory with the code.
After that I call CreateRemoteThread() to invoke that code, creating me a hRemoteThread. I have verified that the remote code works as intended. Note: this code simply returns, it does not call any APIs other than LoadLibrary() and GetProcAddress(), followed by calling the exported stub function that currently simply returns a value that will then get passed on as the exit status of the thread.
Now comes the peculiar observation: remember that the PROCESS_INFORMATION::hThread is still suspended. When I simply ignore hRemoteThread's exit code and also don't wait for it to exit, all goes "fine". The routine that calls CreateRemoteThread() returns and PROCESS_INFORMATION::hThread gets resumed and the (remote) program actually gets to run.
However, if I call WaitForSingleObject(hRemoteThread, INFINITE) or do the following (which has the same effect):
DWORD exitCode = STILL_ACTIVE;
while(STILL_ACTIVE == exitCode)
{
Sleep(500);
if(!GetExitCodeThread(hRemoteThread, &exitCode))
break;
}
followed by CloseHandle() this leads to hRemoteThread finishing before PROCESS_INFORMATION::hThread gets resumed and the process simply "disappears". It is enough to allow hRemoteThread to finish somehow without PROCESS_INFORMATION::hThread to cause the process to die.
This looks suspiciously like a race condition, since under certain circumstances hRemoteThread may still be faster and the process would likely still "disappear", even if I leave the code as is.
Does that imply that the first thread that gets to run within a process becomes automatically the primary thread and that there are special rules for that primary thread?
I was always under the impression that a process finishes when its last thread dies, not when a particular thread dies.
Also note: there is no call to ExitProcess() involved here in any way, because hRemoteThread simply returns and PROCESS_INFORMATION::hThread is still suspended when I wait for hRemoteThread to return.
This happens on Windows XP SP3, 32bit.
Edit: I have just tried Sysinternals Process Monitor to see what's happening and I could verify my observations from before. The injected code does not crash or anything, instead I get to see that if I don't wait for the thread it doesn't exit before I close the program where the code got injected. I'm thinking whether the call to CloseHandle(hRemoteThread) should be postponed or something ...
Edit+1: it's not CloseHandle(). If I leave that out just for a test, the behavior doesn't change when waiting for the thread to finish.
The first thread to run isn't special.
For example, create a console app which creates a suspended thread and terminates the original thread (by calling ExitThread). This process never terminates (on Windows 7 anyway).
Or make the new thread wait for five seconds then exit. As expected, the process will live for five seconds and exit when the secondary thread terminates.
I don't know what's happening with your example. The easiest way to avoid the race is to make the new thread resume the original thread.
Speculating now, I do wonder if what you're doing isn't likely to cause problems anyway. For example, what happens to all the DllMain calls for the implicitly loaded DLLs? Are they unexpectedly happening on the wrong thread, are they being skipped, or are they postponed until after your code has run and the main thread starts?
Odds are good that the thread with the main (or equivalent) function calls ExitProcess (either explicitly or in its runtime library). ExitProcess, well, exits the entire process, including killing all threads. Since the main thread doesn't know about your injected code, it doesn't wait for it to finish.
I don't know that there's a good way to make the main thread wait for yours to complete...

Delphi threads and variables

So this is my question , threads are so confusing for me , let's say I have 5 threads , and 50 or 100 or more sites. So as far as I've learned about threads , I can make constructor create (link:string) and start new threads with different links , but than I wold need to make as much threads as the number of links I need to parse.So how can I make variable link shared between threads , so when thread one downloads link listbox1.items[0] it tells others that number 0 is downloaded and next thread should ask what link should I download and get answer listbox1.items[1] and so on until they download all links when they should terminate.
Can anyone provide me with simple example of how can this be done. Threads are killing me :(
You could have a thread-safe list of URLs to process, and a static-sized pool of worker threads each taking an unprocessed URL from the list at a time, processing it (downloading and parsing) and adding any found new URLs to the list, in a loop, as long as there are any unprocessed items in the list. Keep finished URLs in the list, only mark them as done, to avoid recursion.
Sounds like you simply need to set up a critical section.
This needs to be set up around the code segment which reads the next URL. To do this you would typically place a semaphore at the start of the code so that only one thread can enter it at any time. The semaphore is reset at the end of the code. As each new thread sees the URL list has expired, then it terminates.
Typically semaphores are boolean, but they can be integers for example if you want to allow a specific number of threads to enter the region at any time.
In your case you can simply set up a global boolean variable (visible to all threads), say "fSemaphore".
At the start of the region, the thread checks the flag. If it is false it sets it to true and enters the region (to get the next URL).
If it is true, then it loops - e.g. repeat sleep(0) until (not fSemaphore).
When it exits the region it set fSemaphore := False;
Obviously you need to make sure you guard against a possible infinite loop scenario...
Define a 'TURI' class for the request URI, result, error message and anything else needed for the web query except for the component to be used for the URI access. Descending from TObject shoud be fine. Create, initialize 100 of these and push them on a producer-consumer queue, (TObjectQueue, TCriticalSection and a semaphore should do fine). Hang a few TThreads off the queue that loop around and process the TURI instances until the queue is empty, whereupon they block.
You do not say what action you need taking with the processed TURI's - they will need freeing somewhere. If you wish to notify the main thread, PostMessage the completed URI's and free them in the message-handler.
Terminate the threads? Sure, if you really have to, then queue up some object that signals them to commit suicide, (a NIL maybe - the threads can check for 'assigned' just after popping the queue). When doing something like this, I oftem just leave the threads lying around even if I don't need to process any more URI during the app run - it's not worth the typing of terminating them.
Sadly, the Delphi examples and, I'm afraid, many textbooks, dont' get much further than suspend/resume control of threads, (don't do it), and 'TThread.Synchronize', 'TThread.WaitFor' and 'TThread.OnTerminate'. If you get a textbook like that, take it outside and burn it - you will learn next-to-nothing good.

Delphi - Help calling threaded dll function from another thread

I'm using Delphi 2006 and have a bit of a problem with an application I'm developing.
I have a form that creates a thread which calls a function that performs a lengthy operation, lets call it LengthyProcess. Inside the LengthyProcess function we also call several Dll functions which also create threads of their own.
The problem that I am having is that if I don't use the Synchronize function of my thread to call LengthyProcess the thread stops responding (the main thread is still responding fine). I don't want to use Synchronize because that means the main thread is waiting for LengthyProcess to finish and therefore defeats the purpose of creating a separate thread.
I have tracked the problem down to a function inside the dll that creates a thread and then calls WaitFor, this is all done using TThread by the way. WaitFor checks to see if the CurrentThreadID is equal to the MainThreadID and if it is then it will call CheckSychronization, and all is fine. So if we use Synchronize then the CurrentThreadID will equal the MainThreadID however if we do not use Synchronize then of course CurrentThreadID <> MainThreadID, and when this happens WaitFor tells the current thread (the thread I created) to wait for the thread created by the DLL and so CheckSynchronization never gets called and my thread ends up waiting forever for the thread created in the dll.
I hope this makes sense, sorry I don't know any better way to explain it. Has anyone else had this issue and knows how to solve it please?
If your secondary thread "stops responding," then I assume it has a message pump. (Otherwise, you need to explain what it stops responding to.) You appear to also wish for the thread to be able to detect when the tertiary thread finishes running. (The "primary" thread here is the VCL thread, which isn't involved at all.)
You tried using WaitFor, but were disappointed when you discovered that it blocks. That's what it has always been designed to do, though. Its behavior in the main thread is where it gets weird, so it's safe to call from the VCL thread even though it was never really meant to be used that way originally.
To process messages and wait for threads to finish running, you need to use one or more of the wait functions from the Windows API. Start with MsgWaitForMultipleObjects. It can wait for various types of kernel handles, including thread handles, but also notify you when messages are available. The idea is that you'll call that function in a loop. When it says messages are available, handle them, and then loop again to continue waiting.
The following is just an outline. You'll want to check the documentation for all the API functions used, and combine that with the rest of the knowledge you have about your own threads.
procedure TSecondaryThread.Execute;
var
ret: DWord;
ThreadHandle: THandle;
Msg: TMsg;
begin
ThreadHandle := TertiaryThread.Handle;
repeat
ret := MsgWaitForMultipleObjects(1, ThreadHandle, False, Infinite, qs_AllEvents);
case ret of
Wait_Object_0: begin
// The thread terminated. Do something about it.
CloseHandle(ThreadHandle);
PostQuitMessage(0);
// Put *something* in the parameter so further calls to MWFMO
// will have a valid handle. May as well use a handle to something
// that will never become signaled so all we'll get are more
// messages. I'm pretty sure you can't pass an empty array of
// handles; there must be at least one, and it must be valid.
ThreadHandle := Self.Handle;
end;
Wait_Object_0 + 1: begin
// At least one message is available. Handle *all* of
// them before calling MsgWaitForMultipleObjects again
while PeekMessage(Msg, 0, 0, 0, pm_Remove) do
case Msg.Message of
wm_Quit: begin
// Do something about terminating the tertiary thread.
// Then stop the message loop and the waiting loop.
Exit;
end;
else begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;
Wait_Timeout: Assert(False, 'Infinity has passed');
Wait_Failed: RaiseLastOSError;
else Assert(False, 'Unexpected return value');
end;
until False;
end;
The part about handling all the messages is important. As soon as you call GetMessage, PeekMessage, or WaitMessage, the OS marks all messages in the queue as "old," but MsgWaitForMultipleObjects will only return when there is a "new" message on the queue — one that arrived after the last call to PeekMessage.
HI, Thanks for your reply, yes i realize that my question isn't very clear and somewhat confusing; so i'll try to clarify things a bit, here goes..
All of the threads described below are derived from TThread.
I have a form which starts a thread but does not wait for it. The thread started by the form calls a function that performs a long task.
The function calls another function in a DLL, the function in the DLL starts a thread and waits for it. The thread started by the DLL function calls another function via synchronize.
Form->Starts a thread but does not wait->The thread calls a functions->The function calls a DLL function->The Dll function starts a thread and waits->The thread started by the DLL function calls another function via synchronize i.e Synchronize(UpdateRecords).
The problem is that the call to synchronize never returns because, from what i can see, it has entered some sort of dead lock.
How synchronize works: Synchronize puts the method call into a queue and sets an event, Synchronize then waits for the event to become signaled. When the main thread is idle it will process the method calls that are waiting in the queue, after it has processed a method call it will signal the associated event so that the thread that initiated the synchronization can continue on.
The thread that was started by the form does not use synchronize to call the function that performs the long task, if it does use synchronize then the application does not dead lock, but this defeats the purpose of use a thread for the long process.
I've tracked down the problem, it seems to be that the TApplication object created by the dll is not processing messages and has a handle of 0, how this happened I don't know (I didn't write the DLL, it was written by someone else), but it is a cause of the problem because it will never process the method called queued by synchronize.
I mentioned earlier that if i call the function that performs the long process from my thread using synchronize then the application does not dead lock. This is because the main thread will be responsible for calling the function that performs the long process. So the long process function calls a DLL function which starts another thread and then calls WaitFor. WaitFor checks to see if the current thread is the main thread, and if it is, it processes method calls which have been queued by synchronize, continuously in a loop until the thread the thread that it is waiting for is released (i.e. the method it queued via synchronize gets called and the wait event is signaled).
In WaitFor, if the current thread is not the main thread then WaitFor simply blocks until the thread it is waiting for is released.
Anyway i can't do anything about the application object in the dll because that dll is quite complex and used by a larger system. I guess i can expose a method in the dll which can process the methods in the synchronization queue, i can then call this method from my application while its idle.
Anyway again thanks for your help but i've solved this problem now.
Using the TThread class or even the Application object in a Delphi DLL is extremely unsafe. The RTL and VCL core classes, globals and singleton objects are designed to exist once per process and can't handle the namespace duplication and incomplete initialization in a stadard DLL library.
You may get around it by building with runtime packages (RTL & VCL are enough; you may also build your own with just the system units you reallt need), in the EXE and all DLLs referencing the runtime units (Forms and Classes, especially) - they get single shared namespace and the full EXE initialization sequence this way.
If you can't modify the DLL at all, you may try to set it's Application.Handle, MainThreadID, SyncEvent and WakeMainThread to the corresponding values in the main EXE module - this may work, but it's just as ugly as it looks like and it doesn't cover all edge-cases (the classes and important globals will still be duplicated).

Resources