Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Clicking too fast for database update... 1

Status
Not open for further replies.

ZoneVM

Programmer
Apr 7, 2005
30
US
I'm having an issue where I am trying to keep a database up to date with a form, i.e. when a user clicks an item on a check list, the database is updated. The problem is that when a user checks and unchecks a box too fast, the form and the database do get out of sync, and an exception is thrown. Can someone tell me a better way to do this? Even with the sleep and the disable/enable things I've added, it is still quite easy to click the form faster than the database update can take place.

Thanks for any tips. The offending function is included below:

void __fastcall TResourcePoolingForm::ResourcesCheckClickCheck(
TObject *Sender)
{
//first make sure there's a pool selected
int pIndex = PoolsList->ItemIndex;
if (pIndex < 0) return;
//also make sure there is a resource selected
int rIndex = ResourcesCheck->ItemIndex;
if (rIndex < 0) return;
ResourcesCheck->Enabled = false;
if (ResourcesCheck->Checked[rIndex])
{
//add a this to the pool
DirectoryDBModule->addResourceToPool(mPools[pIndex]->getIdString(),
mResources[rIndex]->getIdString());
}
else
{
//remove this from the pool
DirectoryDBModule->removeResourceFromPool(mPools[pIndex]->getIdString(),
mResources[rIndex]->getIdString());
}
reload();
Sleep(200);
ResourcesCheck->Enabled = true;

}
 
Hi,

I presume the reload() function shows the updated database entries. What if you put the "Sleep(200)" before the "reload()"?
I cannot see into addResourceToPool/removeResourceFromPool but I can imagine that some database handling will be taken care of in separate threads.
 
Yes, the reload loads the form with the updated entries. The addResourceToPool() and removeResourceFromPool() do the database handling, but they do so in the same thread. They are pretty fast queries, simply adding a row to a table or removing based on a primary key. I'll try moving the sleep function to see what effect that has this evening. I hope it is that simple!
 
It turns out that moving the sleep has no effect. I even increased the sleep to an absurdly long period, and the problem persists. It seems that what is happening is that the form 'remembers' how many times it was clicked, but it doesn't call the ResourcesCheckClickCheck() function for each time. It only calls the function once for all the click events that may be queued up. I guess I need to reflow this method so it doesn't depend on being in synch with the database, unless someone has a better idea.
 
If you can modify the DirectoryDBModule, try setting an event whithin the TDataset::AfterPost event handler. After calling the AddtoPool or RemoveFromkPool procedures, Call a wait funtion on the TEvent object.

Code:
//Globally Declared TEvent object

TEvent evDone;


// somewhere in the initialization code you need to create
// the event object

...
// creating an event with standard security attribs,
// Auto-reset,initially unsignalled and named "evDone"
  evDone =  new TEvent(NULL,false,false,"evDone");
...

// Set the event after changes have posted

TDataSet1::AfterPost(TDataset *this)
{
...
  evDone->SetEvent();
...
};
// changes are in bold
void __fastcall TResourcePoolingForm::ResourcesCheckClickCheck(
      TObject *Sender)
{[b]
int EventResult;[/b]
   //first make sure there's a pool selected
   int pIndex = PoolsList->ItemIndex;
   if (pIndex < 0) return;
   //also make sure there is a resource selected
   int rIndex = ResourcesCheck->ItemIndex;
   if (rIndex < 0) return;
   ResourcesCheck->Enabled = false;
   if (ResourcesCheck->Checked[rIndex])
   {
      //add a this to the pool
      DirectoryDBModule->addResourceToPool(mPools[pIndex]->getIdString(),
         mResources[rIndex]->getIdString());
[b]      EventResult = evDone->WaitFor(2000);[/b][i]
// at this stage, EventResult is going to equal either
// wrSignalled or wrTimeout. [/i]
   }
   else
   {
      //remove this from the pool
      DirectoryDBModule->removeResourceFromPool(mPools[pIndex]->getIdString(),
         mResources[rIndex]->getIdString());
[b]      EventResult = evDone->WaitFor(2000);[/b][i]
// at this stage, EventResult is going to equal either
// wrSignalled or wrTimeout. [/i]
   }
   reload();
[b]// Don't need the sleep function now, waitfor should do it
//   Sleep(200);[/b]
   ResourcesCheck->Enabled = true;

}

I hope I have this right!!

The simplest solution is the best!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top