Let's say I have a form Foo.
How do I create an instance of that which runs in it's own thread and gets updated even though the main application thread might be busy doing something else? For instance handling blocking network communication or something like that.
I understand the fundamentals and that I need to create a new thread, create the form instance in that thread etc. But then I figure I need an update loop for that thread/window and I'm not at all sure how that should look.
You shouldn't create forms in threads any than your main application thread, because windows message queue is associated only with this main thread.
Think differently: To be sure, that your forms are always updated and responsive, create separate threads for busy work like handling blocking newtork communications and so on, not for forms. In such case, after creating new thread, main form continues to pump messages from it's queue, while function in different thread is doing dirty-work that you need. When the working thread finishes, it can inform main thread about results, using PostMessage() WinAPI function. You should just simply provide handlers for such custom messages in your forms, and they will communicate with working threads seamlessly.
Also, if your "busy work" isn't very complicated, you can even deal without additional threads, by running your work in the form thread, and just calling ProcessMessages() function from time to time, to keep the form updated.
Related
As we know, dart is a single-threaded language. So according to the document, we can use Futrure/Stream to implement a async opetation. It sends the time-consuming operation to the Event Queue.
What confused me is where the Event Queue working on. It is working on the dart threat? if yes, it will block the app.
Another question is Event Queue a FIFO queue. If i have two opertion, one is a 1mins needed networking request, the other is a click event. The two operation will send to the Event Queue.
So if the click event will blocked by the networking request? Because the queue is a FIFO queue?
So where is the event queue working on?
Thank you very much!
One thing to note is that asynchronous and multithreading are two different things. Dart uses Futures and async/await to achieve asynchronicity, but Dart is still inherently a single-threaded language.
The way it works is when a Future is created (either manually or via calling an async method), that process is added to an event queue, as you read. Then, in the middle of all the synchronous execution, whenever there is a lull, the event queue can take priority. It can then go through the processes and figure out if any of the Futures have been completed. If so, the result is passed along to any other asynchronous processes that are waiting on that resource, if any.
This also means that, yes, if your program hangs in the middle of an asynchronous operation (with the easy example of an endless loop via while (true) {}), it will freeze the entire program, including the synchronous code and other asynchronous processes still waiting to resolve (even if the conditions allowing them to resolve have already occurred).
However, in your case, this won't be an issue. If you fire an asynchronous process in the form of a network request followed by another in the form of a "click event" (not sure what you're referring to, but I'll assume it's asynchronous as well), they will both be added to the event queue in that order. But if the click event resolves before the network request, the event queue will merely recognize that the network request Future has not yet resolved and will move on to the click event that has.
As a side note, it's worth noting that Dart does have a multi-threading capability, albeit in a fairly roundabout way. Dart has something called an Isolate, which isn't a thread but a completely separate child program. This means that the Isolate cannot access any of the same data in memory as the root program itself. However, data can be passed between the two using SendPorts and ReceivePorts. This makes using Isolates slightly more complicated than threads, but it also means that, if no memory is shared, it virtually eliminates race conditions based on which thread accesses the memory first.
Using C++Builder XE5.
My main form has an Indy blocking socket which I would like to connect to and block on, as soon as the application has started up and the main form shown.
What is the correct way to do this?
In previous versions or C++Builder, OnCreate and AfterConstruction were both unreliable. Normally I put code like this in the main .cpp file, just before Application->Run(), however that is not appropriate here because I am going to block (and rely on the TIdAntifreeze for message processing).
One way I thought of is to define a custom windows message and post that to myself, but I'm wondering if there is a "proper" way.
My main form has an Indy blocking socket which I would like to connect to and block on, as soon as the application has started up and the main form shown.
Do you really need to do blocking I/O in the main UI thread? Blocking operations, such as Indy's socket I/O, should be done in a worker thread instead.
If the main thread needs to block on a socket operation while still processing UI messages, you can use a waitable event object via CreateEvent() with MsgWaitForMultipleObject() in a loop that calls Application->ProcessMessages() only when there are messages to process, breaking the loop when the event is signaled. This is not generally the best option though. An event-driven model, where the worker thread notifies the main thread of activity/results, would be a better choice. You really should never block the main UI thread for anything.
What is the correct way to do this?
I would suggest having the MainForm constructor create a worker thread, and then the thread can manage the socket operations and synchronize with the main UI when needed.
In previous versions or C++Builder, OnCreate and AfterConstruction were both unreliable.
AfterConstruction() is reliable, and always has been. It is only the OnCreate event that was unreliable, and should never be used in C++ in favor of the constructor instead.
Normally I put code like this in the main .cpp file, just before Application->Run(), however that is not appropriate here because I am going to block (and rely on the TIdAntifreeze for message processing).
You really should not rely on TIdAntiFreeze, a worker thread is a better choice.
One way I thought of is to define a custom windows message and post that to myself
That will work. I use that technique myself at times. Just be aware that it is an HWND-based solution, so you need to make sure the HWND you post to is not destroyed/recreated after you post the message and before it is retrieved from the message queue. If you use the MainForm's HWND, post the message in the OnShow event. A better option is to use AllocateHWnd() to create a dedicated HWND for your custom messages.
I'm working on an application, but at the moment I'm stuck on multithreading with rails.
I have the following situation: when some action occurs (it could be after a user clicks a button or when a scheduled task fires off), I'm starting a separate thread which parses some websites until the moment when I have to receive the SMS-code to continue parsing. At this moment I make Thread.stop.
The SMS-code comes as a POST request to some of my controllers. So I want to pass it to my stopped thread and continue its job.
But how can I access that thread?
Where is the best place to keep a link to that thread?
So how can I handle multithreading? There may be a situation when there'll be a lot of threads and a lot of SMS requests, and I need to somehow correlate them.
For all real purposes you can't, but you can have that other thread 'report' its status.
You can use redis-objects to create either a lock object using redis as its flag, create some type of counter, or just true, false value store. You can then query redis to see the corresponding state of the other thread, and exit if needed.
https://github.com/nateware/redis-objects
The cool part about this is it not only works between threads, but between applications.
I'm having a bit of a problem. I want to display a progress form that just shows an animation on a when the main application preforms heavy operations.
I've done this in a thread and it works fine when the user isn't preforming any operations. But it just stops when my main application is busy.
I'm not able to put Application.ProcessMessages in between the different lines of code because I'm using 3rdparty components with heavy processing time.
My idea was to create a new process and in the process create a thread that execures the animation. Now that wouldn't stop the thread form executing when the main application performs heavy operations.
But as I see it you can only create a new process if you executes a new program.
Does any one have a solution on how to make a thread continue executing even when the main application is busy?
/Brian
If your worker thread does not have a lower priority than the main thread, you don't use the Synchronize() method, don't call SendMessage() and don't try to acquire any synchronization object that the main GUI thread has already acquired, then your secondary thread should continue to work.
As the VCL isn't thread-safe people do often advise to use Synchronize() to execute code to update VCL controls synchronously in the context of the VCL thread. This however does not work if the VCL thread is itself busy. Your worker thread will block until the main thread continues to process messages.
Your application design is unfortunate, anyway. You should perform all lengthy operations in worker threads, and keep the main thread responsive for user interaction. Even with the fancy animation your app will appear hung to the user since it won't redraw while the VCL thread is busy doing other things and processes no messages. Try to put your lengthy code in worker threads and perform your animation in timer events in the main thread.
Your logic is backward. Your thread should be doing the "heavy work", and passing messages to your main application to update the progress or animation.
If you leave all the "heavy work" in your main application, the other thread won't get enough chances to execute, which means it won't get a chance to update anything. Besides, all access to the GUI (VCL controls) must happen in the application's main thread; the VCL isn't thread-safe. (Neither is Windows itself, when it comes to visual controls.)
If by "Does any one have a solution on how to make a thread continue executing even when the main application is busy?" you mean that main thread is busy you should move the code that is consumming main thread to another other thread. In other words main thread should be responsible for starting and stopping actions and not executing them.
Disclaymer:
Actually I don't know delphy but I think/hope the concepts are quite similar to C++ or C#.
I coding a service application that have two threads.
First thread, show a form with label.
Second thread, query ADO.
First thread always freezing with Hourglass cursor and no label caption.
Please help.
If you're trying to show a form from within a thread that is not the main thread, then you will run into strange things like this. The most notable of which is that if the form and label are created in the non-main thread, then you don't have a message loop to process the messages. If the form was created in the main thread, but you're attempting to show it from the non-main thread, then it is likely a dead lock due to how Windows deals with messages and threads.
When a window handle is created it is tied to the thread on which it was created. This means that Windows will ensure that any messages sent to that handle are processed on that thread.
I would strongly suggest you read up on how window messages, message queues, and handles all interact and function in a multi-threaded environment. If not done correctly, you are assured of some very odd and possibly unpredictable behavior.
I would call your condition either a Race, a Deadlock, or some other kind of error like that. As Allen says, if the background thread makes ANY direct access to the VCL controls, without using TThread.Synchronize(myMethod) to invoke the myMethod that touches your VCL foreground, then this alone would cause your trouble.
Post more information, including a sample of your code please.