Re: ways to provide a synchronous response from an asynchronous task
Originally Posted by Eduardo-
The asynchronous component usually notifies that it finished with an event, but there could be also a property that one can check to see whether it finished or not, for example Object.StillExecuting
I did not read the full thread. But my generic Multithreader comes into my mind. http://www.vbforums.com/showthread.p...%29&highlight=
It is a class object which is event driven. When a new thread is started a asynchronous event is fired and within that event a synchronous callback to the original thread can be started. The original thread will be suspended until that callback is finished and it returns back to the asynchronous event and when that ends the new thread is terminated.
You may create as many threads as necessary. There is a demo project included which shows how to use it.
The downside is that it is a separate Ax-DLL. However, there is a Registration-Free (Side-by-side) solution available. (via manifest)
Re: ways to provide a synchronous response from an asynchronous task
Thanks Krool for sharing that project.
At some point I'll have to venture into the world of threading. I still didn't have to do a very intensive and long processing task, but when I have, I'll need it.
I see threading as a way to take advantage of the new processor architectures (of having several cores). Aside from that, I don't know if there are other advantages.
About the other subject of not locking the IDE when doing a long task, it's logically impossible to avoid reentrancy, unless disabling the UI (or the functions of the UI that can cause reentrancy for the particular case).
I don't think that threading could change that, since as I see it, it's logically impossible: if the UI is not locked or disabled, then the user can fire something that can cause reentrancy.
The only things to do are whether to disable the UI or to handle the reentrancy.
Re: ways to provide a synchronous response from an asynchronous task
Originally Posted by Eduardo-
Thanks Krool for sharing that project.
At some point I'll have to venture into the world of threading. I still didn't have to do a very intensive and long processing task, but when I have, I'll need it.
I see threading as a way to take advantage of the new processor architectures (of having several cores). Aside from that, I don't know if there are other advantages.
About the other subject of not locking the IDE when doing a long task, it's logically impossible to avoid reentrancy, unless disabling the UI (or the functions of the UI that can cause reentrancy for the particular case).
I don't think that threading could change that, since as I see it, it's logically impossible: if the UI is not locked or disabled, then the user can fire something that can cause reentrancy.
The only things to do are whether to disable the UI or to handle the reentrancy.
When the thread is started, you can check in your UI if the thread is still active. Thus you can avoid the reentrancy.
In my demo project the form cannot be closed until the asynchronous thread is finished. But of course it can be a check to not start a new thread.
Re: ways to provide a synchronous response from an asynchronous task
Originally Posted by Krool
When the thread is started, you can check in your UI if the thread is still active. Thus you can avoid the reentrancy.
In my demo project the form cannot be closed until the asynchronous thread is finished. But of course it can be a check to not start a new thread.
I've run your demo project.
If I start the task, then show a form, then leave it open until after the task ends, I get a crash.
Re: ways to provide a synchronous response from an asynchronous task
Why not just Trust the Events, Luke?
After all, that's why we have them. Everything that goes on in your VB6 code after Sub Main is event handler code anyway. Well that and the occasional COM callback or two but those are usually invoked via code in some event handler too.
You'd probably be less interested in the Attribution control itself than the Form hosting it. However it does an async operation itself as well.
The flow of Form1's logic shouldn't be too hard to follow. The key is state management, tracking what you are doing by making the Form logic stateful. In this case a simple variable "RequestType" manages most of it along with a few other variables to hold intermediate results.
I think you are just fighting the paradigm. You might find a way to de-async your program flow, but I doubt it will ever be worth the cost in extra code, complexity, and long-term effort to maintain.
Re: ways to provide a synchronous response from an asynchronous task
Originally Posted by dilettante
Why not just Trust the Events, Luke?
After all, that's why we have them. Everything that goes on in your VB6 code after Sub Main is event handler code anyway. Well that and the occasional COM callback or two but those are usually invoked via code in some event handler too.
You'd probably be less interested in the Attribution control itself than the Form hosting it. However it does an async operation itself as well.
The flow of Form1's logic shouldn't be too hard to follow. The key is state management, tracking what you are doing by making the Form logic stateful. In this case a simple variable "RequestType" manages most of it along with a few other variables to hold intermediate results.
I have XP SP3 but I think I don't have WIA 2.0, so I cannot run it.
But I've read the description from your post.
I think you do the "normal" thing of disabling the controls when the call is still in progress, or are you doing something else?
Originally Posted by dilettante
I think you are just fighting the paradigm. You might find a way to de-async your program flow, but I doubt it will ever be worth the cost in extra code, complexity, and long-term effort to maintain.
Well, that's a good point. I'm not too sure either, mainly because the code flow is hard to follow. And It's hard to follow because some situation arise in a timer call, but the condition is generated in another (previous) timer call.
Now it is working, and so far it seems to be working well.
But sometimes I wonder if I'll remember how it worked when I have to make modifications in the future.
The idea was to provide an interface as simple as possible, similar to a normal VB control, even when it internally works with (almost) all asynch operations.
But I'm not too encouraged to move to that path with this project because it will add the difficulty of the crasshes in the IDE.
I would get rid of the difficulty of following the code driven by the timer but add this other problem.
And I would have to rewrite everything again.
Re: ways to provide a synchronous response from an asynchronous task
Threading just brings in new complexities. I doubt that is your answer.
My example only disables controls that make no sense to be enabled at various times. The "Get quote" button makes to sense to be enabled before the "categories" list has been populated or while a "Get quotes" is already in progress.
For example the Attribution control remains enabled and can be clicked at any time.
There really is no "something else" going on. The program just tracks its state as it works through one async request after another. As each completes it handles it and then it advances to the next state and initiates the subsequent request.
The code in Form1 isn't that complicated. Most of it is involved with "printing" text over an image. Most of the rest involves extracting data from the returned JSON responses.
When we boil it down we are left with:
Code:
Option Explicit
Private Enum RequestTypes
rtCategories = 0
rtQuote = 1
rtBackground = 2
End Enum
Private RequestType As RequestTypes
Private WithEvents Req As WinHttp.WinHttpRequest
Private Sub Command1_Click()
RequestType = rtQuote
Req.Open "GET", REQUEST_QOD, True
End Sub
Private Sub Form_Load()
Set Req = New WinHttp.WinHttpRequest
RequestType = rtCategories
Req.Open "GET", REQUEST_CATEGORIES, True
End Sub
Private Sub Req_OnResponseFinished()
Select Case RequestType
Case rtCategories
'Process "categories" response.
Case rtQuote
'Process "quote" response.
Req.Abort 'Finishes up so we can make a new request.
RequestType = rtBackground
Req.Open "GET", background_picture_URL, True
Req.Send
Case rtBackground
'Paint the background picture, draw text on top of it.
End Select
End Sub
Re: ways to provide a synchronous response from an asynchronous task
Originally Posted by dilettante
Threading just brings in new complexities. I doubt that is your answer.
My example only disables controls that make no sense to be enabled at various times. The "Get quote" button makes to sense to be enabled before the "categories" list has been populated or while a "Get quotes" is already in progress.
For example the Attribution control remains enabled and can be clicked at any time.
There really is no "something else" going on. The program just tracks its state as it works through one async request after another. As each completes it handles it and then it advances to the next state and initiates the subsequent request.
The code in Form1 isn't that complicated. Most of it is involved with "printing" text over an image. Most of the rest involves extracting data from the returned JSON responses.
When we boil it down we are left with:
Code:
Option Explicit
Private Enum RequestTypes
rtCategories = 0
rtQuote = 1
rtBackground = 2
End Enum
Private RequestType As RequestTypes
Private WithEvents Req As WinHttp.WinHttpRequest
Private Sub Command1_Click()
RequestType = rtQuote
Req.Open "GET", REQUEST_QOD, True
End Sub
Private Sub Form_Load()
Set Req = New WinHttp.WinHttpRequest
RequestType = rtCategories
Req.Open "GET", REQUEST_CATEGORIES, True
End Sub
Private Sub Req_OnResponseFinished()
Select Case RequestType
Case rtCategories
'Process "categories" response.
Case rtQuote
'Process "quote" response.
Req.Abort 'Finishes up so we can make a new request.
RequestType = rtBackground
Req.Open "GET", background_picture_URL, True
Req.Send
Case rtBackground
'Paint the background picture, draw text on top of it.
End Select
End Sub