Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ERROR: AV's and IWButton.picture.data: the parameter is incorrect
#31
Hi mrSpock,

Thank you for your example code. The way you have changed it to, is the way I have had my program all along, from the beginning. As mentioned earlier I have had only 1 or 2 local vars, after the end of the form class and public definitions, but before the word "Implementation" and for those forms I have moved it up into the public part.

And also only a few functions (like your Y_OD_X example) have been used in the implementation part of two forms, without the "TIWFORM7" part of the procedure/function name, and without being defined in the public part. They too have now been properly defined, and of course your TIWForm7 has been changed to the name of my form. But so far it has not solved my problems.

I'm still on square one. I'll do some more testing today to isolate the problem further. As my application covers a lot of user data entry forms, where there do not seem to be a conflict when a user select a record, even when 2 uses try to select an item at the same time, I have a feeling it is mostly when executing longer running selects (+/- 3-4 seconds), I have the problem. It is still a problem, but indicated the problem might lie elsewhere.

I'll keep feeding this thread as I find out more.

Finally I'd say I agree, it would have been nice if documentation had been up to date.

Regards
Soren
Reply
#32
Soron,

I hope you remember that database operations must be done in the transaction. In my program I did it in such a way that the transaction and its possible rollback was done in a loop repeated three times. There was a random millisecond gap between loop repetitions. Thanks to this, I avoided erroneous entries into the database if more than one user was writing to the same records at the same time. All the transaction must be done instant in a split second. Do not leave a locked record for a few minutes because the user is editing the record.

It seems that intraweb requires some additional steps to ensure independent multi-user access to a database and this is a bit related to my problem I just had with these bitmaps.

Regards
Mariusz
Reply
#33
mrSpock,

To be honest, I perform both Insert, update and delete through the ADOQuery without any transaction control. In a webservice running alongside this program on the server, also as a service, I'm using only ADOStoredProc, calling only stored procedures, and all of those doing insert, update or delete, is always wrapped in a begin trans with either commit or rollback. If it turns out to be a problem, I change to using ADOStoredProc instead-

How do you do what you describe, in the program using a ADOQuery ?

The problem I'm facing seem to only affect the Select I let users perform after entering values for a where clause. Those selects will search millions of rows, but always with top(30) or max top(100) limiting search time. Nevertheless, each select takes 2-4 seconds. And that's where the problem appears to be.

Various tests has shown that selecting individual rows, like an Customer from a Customers tabel, never mix data, even though they are activated at the same time. Also, saving (updating) at the same time seem not to give any trouble. I even have a so called Real-Time display, listing the 15 last rows of a table based on a given where condition, and being refreshed every 5-10 seconds. And even when 2 such functions are displaying various rows at the same time, and again are being activated at the exact time, they do not mix data.

The selected data, both for the search select that goes wrong, and for the selects listing the real-time added rows, are shown in a grid. In my case it is a TMS IwAdvWebGrid (not db aware) but one I populate manually from query fieldbyname to grid.cell[x,y].

It is strange I do not see the problem in the Real-Time displays, but it could be due to the time it takes to run the select. The Real-Time is always limited to one of the Key values of the table and is quite quick, whereas the larger search select, is not using the key field of the table. It appears only to affect a longer running select, even though we are talking max. 3-4 seconds.

I suppose Tran, Commit and Rollback do limit access to tables but not when it is a select, so I cannot use it for this.

I'll keep trying,

Regards
Soren
Reply
#34
Hi everyone,

I have finally found the reason and solved my problem.

After a lot of changing components around, setting adoquery connection to various dbconnections, and even tried setting the adoquery connectionstring as I would set it in the ADO DBConnection, a number of different tests pointed out that it was just in one function where the problem was. As described above, it was the large Select function giving problems. And with a similar, however not as large, function not giving problems, I found the culprit: One single variable, holding the generated Select statement before execution, was still outside the secure surroundings of the Form Class definition. Once it was moved inside, into the Public section, the function started to behave as expected.

A heavy weight was lifted from my shoulders....

Now all that just remains is to move all components back to their original location being connected to a local dbconnection, not the one previously defined in the UserSession. That should work, and I will test it. I will let you all know once I'm done.

One thing though: It do not appear to be necessary wrapping ADO calls in thread safe code, unless of course the code inside a form, actually activates separate threads, using the same ADO components. That is not the case for me, so I do not need to. And of course I will still need to enclose Inserts, updates and Deletes, in transaction-commit-roolback code, but that another issue.

Thanks to everyone for your help and comments so far. I have learned a lot and I hope some of you who has participated in the thread, or just followed it, have learned something as well.

Regards
Soren
Reply
#35
(02-09-2020, 07:51 PM)MrSpock Wrote: So I have moved all variables from section
implementation=>var
to
form class=>public

and changed all procedures and functions to
form class=>public
in a very well known way

altogether it took less than half an hour.

Now two sessions in two browsers seem to work independently from each other. The problem is solved.
This was probably so obvious that it had not been mentioned in intraweb manual.
-------------

Glad to see that you solved that situation! Because of the way that an IW application works, with a server application that deals with several sessions in independent threads we have to rethink the use of memory in our applications, but once you internalize the idea, all works well.

However, I agree that IW deserves better documentation. When I began with IW a bit more than three years ago, I just found two outdated IW manual "IntrawebManual" from Atozed and "VCL_for_Web" from Bob Swart. I think that IW would be more successful if a good manual was produced. IW 17 is coming and it would be a good opportunity to bring together a REALLY good manual, the same way that IW concurrents already do with their products when talking about the manual. I think that they should consider that the full potential of the product can't be achieved only through the available examples. Learn by example should be a complement of IW education, not the main approach.

Regards,
Joao Lira.
Reply
#36
So eventually Soren it has turned out that your problem is the same as mine.

Some databases require a transaction even for SELECT. I have not been doing anything with databases for a couple of years now. Several years ago I used "interbase" database. I was not satisfied with automatic built-in transaction control in database components so decided to do it manually. It was a lot of work giving the user a message about the fields that have been changed by another user if transaction failed. I had to show two copies of the record, the changed one and what the user wanted to update.

That is a pity your SELECT cannot use indices. It must be a pretty complicated query. Sometimes a compound index can be used or at least for some fields and it should speed up the query.
Reply
#37
Geez... this thread is now huge... it will take some time to go through it....
Reply
#38
Regarding "oh the documentation doesn't say that"

http://docs.atozed.com/docs.dll/developm...ation.html

Extracted from there:

Quote:Notes:

To store session related variables, create members of the TUserSession class.
Do not work with variables declared in the var section, as these are global to all threads and won't reflect session data properly.

There are several other documents that mention that global vars should NEVER EVER used in any multithreaded application, not only IntraWeb.
Reply
#39
(02-09-2020, 10:28 AM)MrSpock Wrote: That needs more explanation.

I have some variables declared as session variables but almost all of them are declared in the implementation part of the unit. For example I create bmp: TBitmap in form onCreate and remove it in form onDestroy. I expect the bmp variable to be different for each user. All forms, while creating them, should, as I expect, belong to the user's session. So the bmp should be independent for each user connected at the same time to a different session. But now I see the same variable is shared between users, which should not happen. When I use
TIWForm1.Create(WebApplication).Show
in fact user2 gets the same implementation part variables as user1 has got. User1 sees variables of user2 and vice versa!!

But moving a number of variables from many forms to usersession unit does not make sense, does it? This way intraweb is of no use to me.

As I explained in another thread yesterday, no global variables are safe even if declared in Implementation section. The fact that it is not "visible" outside the scope of the unit doesn't make it safe because multiple instances of the same session will share the same variable.

Global variables are *evil*. Even more in multi-threaded apps.

This has nothing to to with "Intraweb". That's how memory management works. No Delphi, Free Pascal or C or C++ global variable will *ever* be automatically thread safe doesn't matter what you do. You can use plain WebBroker applications made with Delphi and you will find the same "issue" (which is no issue at all, i.e. that's how compilers and memory managers work and has always been).
Not even in C# you will get that (although you don't have global variables like in Delphi, the concept is the same and there is no "automatic" management like this).
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)