Delphi, ClientDataSet and threads - multithreading

I have a TClientDataSet that holds information and is not linked to any GUI component.
In a thread I locate the relevant record, go into edit mode and change the values. Because it happens inside a thread, I use TCriticalSection before locating until after posting. It looks something like that:
cs.Enter;
if not cds4Process.Locate('locator',locator,[]) then exit;
cds4Process.Edit;
cds4Process.FieldByName('field1').AsDateTime := pDay;
cds4Process.FieldByName('field2').AsFloat := amnt;
cds4Process.Post;
cs.leave;
cds4Process is located on the main form and it is not linked to any GUI component, I don't pass it as a parameter to the thread.
I execute the thread several times and in some point, I get an error that says that cds4Process is not in insert or edit mode. even though the above code sequence is the same in all the places I use cds4Process.
Any idea? What am I missing?

I would place everything related to the TClientDataSet (its connection component, persistent fields etc.) on a TDataModule instead on the main form, and then create an instance of this data module in the thread.
Using this thread-bound TDataModule as a container for data access components would allow visual design, and prevent me from using the VCL main thread accidentally.

Related

How to correctly call ComponentDialog from another ComponentDialog

I've been battling with this over the last day, can't seem to get it to work correctly. I would share code but I feel it might confuse matters.
I've created a few ComponentDialogs that are needed to be included in other ComponentDialogs including the main bot.js.
ComponentDialogA is being imported into the main bot.js which gets called fine when I do a replaceDialog or beginDialog. But when I try can call ComponentDialogB from ComponentDialogA it just returns to the last point of ComponentDialogA and fails to hit ComponentDialogB.
So my sub questions are as follows:
Do I need a custom state accessor for each ComponentDialog in order
to do what I want to achieve or is that just for storing specific
data related to that dialog as opposed to the actual dialog position
Related to the first do I need a new dialogSet per ComponentDialog to
handle child ComponentDialogs, to use this.dialogs.add instead of
this.addDialog?
Am I just being dimwitted and messed up my code
somewhere?
I'll try and simplify my code and share later.
Many thanks,
First, there is currently a limitation in v4.2.x version of the libraries that prevent ComponentDialogs from accessing dialogs outside of itself in any way. This means that the dialogs inside of a ComponentDialog can only ever begin dialogs that are siblings to them within that ComponentDialog and never access the outside world.
In 4.3.x timeframe it will be possible for a ComponentDialog to begin a dialog "up" its ancestry chain as well. This means that, for your scenario, if both ComponentDialogA and ComponentDialogB were registered in the same parent DialogSet, ComponentDialogA would be able to call beginDialog('ComponentDialogB' ...) and it would find it.
To be clear though, you will still not be able to address individual dialogs within ComponentDialogs from the outside. Meaning, if your ComponentDialogB had a SubDialogX inside of it, something outside, such as ComponentDialogA, cannot start that "inner" dialog explicitly. Make sense?

UWP bitmapimage on background thread

I have a simple question.
In my UWP app I am using multiple threads and while on a background thread when i try to create a simple BitmapImage by using code: var image=new BitmapImage();. It throws an exception
The application called an interface that was marshalled for a different thread.
this exception occurs on the very line where I try to create the image. I simply want to create this image, deal with its properties and then store it in my datalist.
Note: datalist is a simple public static property which is accesible throughout the app. thankyou
I can't see the full context from the question, so I am not sure why this exception is bubbling up, but one sure way to fix it is using CoreDispatcher.RunAsync().
The documentation says:
If you are on a worker thread and want to schedule work on the UI thread, use CoreDispatcher::RunAsync.
If you are using MVVMLight, you can also make use of it's DispatcherHelper class' CheckBeginInvokeOnUI method. It's a bit better, since it first checks which thread it is called on and if it's the UI thread, it executes the action immediately and passes it to the UI thread only if needed.

MFC/3rd party multithreading hang

I'm currently working on a program using MFC. The current third party function starts a thread after an action has been completed using MFC (ie. Checking a checkbox, which starts a MFC thread I believe).
The problem occurs when I check the checkbox, at which point the entire program hangs. I read a few interesting discussions on CProgramming and msdn, it seems that the problem occurs because the new third party thread is calling WaitToSomething() when MFC is updating a control.
Something interesting to note:
When I debug the program, the program hangs (aka. repeatedly calls WaitToRead() ) after I check the checkbox and a new thread is trying to start
When I run the program without debugger, the program is fine UNTIL I switch to another window (ie. Internet browser, Notepad, etc)
My hypothesis:
check to make sure that MFC has finished updating the control before starting a new thread
If anyone has any suggestions or solutions, please leave a comment. Thanks.
Edit:
MFC is not thread-safe at object level (only at class level), so problem occurs when two threads work on the same CButton object.
Q: How do I make it thread safe?
A colleague helped me figure out what the problem was.
The reason why it was hanging is because that the control containing the checkbox is a child dialog, and when it finished updating the message never got passed up to its parent (so when 3rd party thread calls WaitFor(), the MFC thread never completes because a parent dialog thinks its child is still updating the controls).
Fix:
Under 'Properties' in the child dialog's control, set the 'Control' flag to true (and if it has children, set the 'Control Parent' flag to true as well).
Hope this helps.

Cocoa Stop Button

I load a file from the disk, chunk by chunk, and I would like to grant the user the opportunity to click on a button and stop loading. I already know how to do that with threads (e.g. detachDrawingThread) but here I wouldn't use that way. The loading method in facts should return a bool value, it's called from different points and it's usually followed by many other lines of code. So I can't launch the thread and leave it work in a separated thread. And I can't split my code so easily. It's really complicated.
I just need to detect if the user clicked on a given button. That's all.
Is a quick and simple way to do that without rewriting my whole app?
Your loading routine must be using some sort of loop. Create a boolean and in your loop test for the condition of the boolean. Then in your button selector, set the selector to change the status of the boolean. Once your loop goes around again, it will exit and stop loading data.
First rule of good Mac apps:
Don't block the main thread
Some options:
Do the work on a background thread. Sounds like you don't want to/can't in this case
Use something like NSURLConnection to process the data in small chunks on the main thread as it's read in, rather than running a continuous loop
Run the event loop periodically while loading data so UI events can be processed
Thanks, I usually use threads, but in this case in order to use a thread I should almost re-write my app... So I have found a quick solution. Within the loop I added:
while(event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]){
[NSApp sendEvent:event];
}
So when the user clicks on the button to stop the loop, I post a notification and exit the loop. It works well.

How to avoid use of timer when using TThread to communicate with UI thread

I have a TThread which receives and sends to a device on a COM port. After I read the data, I want to activate the GUI (not in the same thread) using Synchronize(function name). However, when I call the GUI's form function to perform a button click, I get an access violation. I checked to see if the form's value is null and it is not, since this would be an obvious reason for access violation. Right now, I am setting global flags and using a timer that continuously checks to see if a certain condition is met and if so, then I fire off the button click event in that form. That seems to be the only way to avoid getting the access violation.
I really don't like timers so is there a way to avoid having to use a timer on the form?
You can post a message to the window in question. The timer works in a similar manner. It just fires off a windows message inside the form. You obviously have a handle to the window.
CWnd::PostMessage(...) Don't use send message, it gets processed inline and could cause your thread to stop working.
Typically when you have a worker thread that attempts to access Guithread, they conflict. It's been a while since I've used MFC and threading but that's what I remember. I believe it's documented to work that way.
I found the problem. I thought I was checking if my Form was null, but I was not. I fixed it making sure the form I was referencing is not null.
Edit: Turns out that one of the forms that is called when I call Fbutton1Click() is Modal so it blocks my thread. I ended having to go back to a timer to call the button click instead.. oh well.

Resources