Handling unexpected events in winform application - c#

I have a win-form application developed in .net 4.0 and using SQL 2008 as DBMS.
User can open an item from a list of item and every time they open, I am updating the database with the userId to state the particular item is opened by particular user so other users can’t open the same item at same time. Also when user closes the item I am resetting it back to normal where others can open.
But I am wondering how to update the database if some ones system got crashed/stuck or something similar. Is there any good solution to handle these kinds of situations?

One solution would be to add a time stamp column into the data table. Every time a user accesses an item (in addition to other work) you set this time stamp value.
You can then have a separate task/service that iterates thought the records and releases any expired locks once in a while.

So you're trying to implement your own locking mechanism. See how to mitigate the problems of Deadlocking that should give you an idea. Basically either you use notifications or stamps to track lock's owner status (if it's dead or still using the resource), preventing resource starvation.
Requested example
There are 2 users. User A and User B.
User A open a view within your app, then two things happen:
You update the DB and set the stamp to the current time.
You start a new background thread who will be responsible to mantain the lock. This background thread must wait N-Delta where N is the maximum minutes the resource can be locked without renew and delta is the delta for update time. So, for example, suppose a view can be locked for maximum 15 minutes without user activity, then your thread must wait 15-1 (taking that will probably take 1 minute to notify DB "better be caution with this time").
Then User B try to access to that view, you check on the db for the resource and for the lock table and if there's a lock on that view whose time isn't superior from 15 minutes then you deny access. BUT if time is most that 15 minutes you grant the access to the User B and remove the access from the User A.
If either User A or User B successfully close the view, then you just remove the entrance from the DB.
This is a very simple example but should give you an idea of what I mean.

I have faced similar situation before. In such cases you will have to assume how much maximum time would a user take to action on that item (say 15 mins). Create a table called item_lock with 2 columns: item_id, lock_aquired_time. Every time a user clicks on any item, a record would get inserted into this table. If any other user tries to open that item.. a notification would pop up on his screen that the resource is locked for actioning by XYZ. Futher you will need to create a service which would run say every minute and will remove any record which is older than 15 mins.
PS: Whenever any user has finished taking action on any item.. that row would get deleted from item_lock table.

Related

Conducting timed tasks in a web-site - best practice?

What might be the best way to implement timed-task in a web-site (asp.net) environment ?
Say clicking a button locks it for 4 hours, or a day. How would I go about implementing the process of counting those 4 hours, (or 1 day) and then unlocking the button) ?
Keep in mind this is a web-site: Do I
save the current datetime stamp to the DB (I'm logged in as a registered user to the web-site)
every time I visit the page with the button I retrieve the stamp and the duration
and calculate how much longer I have to wait, until the button is unlocked.
(And possibly implement a JS (for example) count-down counter that would show near the button)
I'd assume using session variables or cookies is a bad idea, as I may close my web-site or delete my user data and thus loose the above.
Since your requirement is to support this across sessions, then it definitely needs to be in the DB.
DB
Add a LockedUntilUtc column that indicates the date/time that the button should unlock. Better yet, name the column to represent the business model. Maybe you are writing an HR app the has a raise approval process, and there is a mandatory 7 day waiting period before the manager can release the raise to allow HR to review, and the button is laballed "Publish Raise" in which case I'd name it something like PublishRaiseAvailableUtc.
I've dealt with lots of scenarios like this, and it's often simpler to use the date/time that an event needs to occur. As opposed to saving the beginning of the timer and always having to add 7 days everytime you need to make a calculation.
UI
Send this value down with the page as a hidden value. Write javascript using the framework of your choice, or just something as simple as setTimeout which will fire to unlock the button at that point in time.
Do not worry about trying to come up with a convoluted way to prevent the user from unlocking the button by manipulating the HTML. You should assume they can unlock the button if they put effort into it. Given that assumption, we need server side logic to validate the request.
Server Post Validation
When the user clicks the button, and the POST is sent to the server, then server-side code should retrieve the value of PublishRaiseAvailableUtc from the database(do not trust the value posted from the hidden field), and compare that to the server time. I.e. server time should be greater than the PublishRaiseAvailableUtc, assuming you ensure you are comparing UTC times.
I think the best way is saving the day when the button becomes unlocked again. And every time the page is loaded, retrieve that info from the db to check if it should be locked or not.
Another possible way is to use an application variable. But i dont recommend this, because data is stored in memory and because if you reset the app or server, data will be lost.
You first problem is in your approach. You don't necessarily care how long it will be until the time you've saved, but you definitely do want your button to change when that time comes.
What I might suggest is to load the DateTime value from the database, place it somewhere in the page where JavaScript can read it. Now, one only problem is that some users may be able to locate and modify this value to skip the timer. I'm not personally familiar with a way to circumvent this easily, but you should be able to research a solution.
Once you have the value readable by JavaScript, a loop is probably going to be your best bet for checking the current time against your saved time, then performing whatever action you want.
A do..while loop will probably suit your needs
To avoid performance issues, use setTimeout to delay each loop iteration. The delay doesn't have to be very significant.
In the loop, retrieve the current date and time, then compare it to the date and time you saved in the database. If the current date and time is greater, perform your action.
Now, my idea may not be optimal, but I feel it is at least a step in the right direction. I also suggest a loop so that the user is not required to refresh the page to see what changes resulted from the performed action.
Do not rely on client side validation that the button is locked/unlocked. Always check server side that the click happened during the allowable time. This would prevent someone from "hacking" the page to allow a click outside of the allowable window.

Disable a button for t minutes

I want to disable a button for twenty minutes this should remain disabled even if the application is restarted.
I was thinking doing this by reading and storing the time when the button is pressed, then read the system time every minute and when the elapsed time be 20 or more minutes, enable the button.
I think this would allow me to restore the time when the button was pressed if the application is restarted; and then check for the elapsed time.
Do you think this is a good idea?
Any other option?
Since you want this setting to work even if the application restarts, this won't be possible unless you involve an external agent. A few options that you might try involve:
Read current Internet time from http://time.windows.com or nist etc and store it somewhere (registry or local file). Use a timer within your application that keeps fetching latest time from the Internet and compares it to the save value. This post allows you to read current Internet time using both HTTP and TCP port 13.
Use Windows scheduled tasks. Set a bool flag somewhere (file/registry again) and ask the scheduled task to clear the flag after 20 minutes. This post should get you going with creating scheduled tasks.
Create a Windows service that keeps running in the background that you could call to set the flag and the length of time for which this flag should remain set. The service should run an internal Timer (and should not rely on system time) to keep track of "ticks". After the specified time has elapsed, the service should clear he flag.
Here is what I am thinking,
When the application starts, disable or hide the button
Set the time stamp when disabling/hiding and store in a database table or a file.
Now read every minute or every five minutes - whichever is convenient to see if 20 minutes have elapsed.
IF 20 minutes have passed, remove the entry from table or file.
And if the application crashes or restarts before setting the time stamp:
1.While setting the time stamp, make sure that the table or file is empty. If not, enable the timer - the time stamp is there.
Well if I were you, I'd basically disable the button
and then start a timer, each minuite, the program should write the time left to a file as well as the current time ( you can also decrypt this file, so that users can't change it )
Now when the program restarts, it should read this file, and start a timer according to the written time in the fil :)
If you want the timer to work even when the program is closed, then you might check this out (File.GetLastAccessTime)
Basically, you should compare the (current time) that has been written to the fil, with the last access time, and make a function to get the time left :)
This might not be a perfect solution, but it will work fine ( I guess )
Kind Regards :)

how to handle system wide key events in asp.net application

i am working on an asp.net web application, where tasks are assigned to users, we set standard time to every task, in that standard time period the user has to finish the task, there are two buttons on the page, proceed and save, when a user clicks on proceed button, the time is saved in database as starttime, and when the user clicks on save button, the time is saved in database as endtime. this way we are capturing the time period within which the user is completing the task.
the standard time is set on an average time study basis, not every time the task takes the same amount of time.
often users can complete the task in very less time than the standard time, in this case the users are proceeding the task and even after completing the task, instead of saving it, they lock the system and go for tea breaks and after coming from break, they save the task.
i want to save some information on the web page when they lock the pc even when the browser is minimized.
i tried implementing applet using jintellitype library but its not capturing the key combinations that are used by windows os.
i also tried using Silverlight but there is no such support as in winforms application in Silverlight, i have to create a com component or something that interacts with system32 or some native api. it doesn't seem easy for me, i would like to know if there is such library for Silverlight.
it should be browser independent, i haven't tried ActiveX, but i think it can be done using ActiveX, but i don't want to use ActiveX as it runs only on IE.
i want to know all the possible solutions to achieve this.
thanks in advance.
Why don´t you set a kind of timer-check to know if the last time is too far from the correspondent (and previewed) time to perform the job? If a task may expend, for instance, from 1 to 5 minutes, have 21 minutes is too far.
Why din´t you create a timer to TIMEOUT user? If users know they will be timed-out after some time, probably, they won´t leave to coffre-break during the test (a kind of penalty must be aggregated on this, like start from the initial point if timeout).
Why don´t you automatically save the record after the job finish, instead obly the user to press a button?
Until I know, you can perform SUSPEND mode, but not detect them if started from other apps.

Solution to a timed out/End Date event

Hopefully someone can help me to look in the right direction for a solution to this issue I've come across during the design of a system.
I am creating an auction site in which the auction has a particular end date/time.
I have a .NET Timer displaying the remaining time to the user and when this countsdown it fires and event to update the back end SQL database to say the auction has completed and it informs the winning user and fires a CLOSE function.
How would you recommend doing this for auctions that aren't physically open in a browser at the time so the Timer event never creates this CLOSE event.
Ideally I need to run something at the point in time when an auction closing time has passed?
Thanks
One option is to store in the database the date/time that the auction item ends/closes. Then, don't worry about something reacting to it closing (timer in your case on the client) and updating it closed. What determines it's closed is simply the fact that now > closed date/time.
EDIT:
In the comment below you stated you also need to send mail when an auction closes. If that's the case, you need some sort of background processing to select all events that are closed and send mails. You can still define closed by storing a date time. That bg processing can select all events where now is greater than closed date and processed bit is false. Once you select those, put them in a durable queue (table in sql, azure queue etc...). Then have the background processing drain the queue. As it processes each item and sends mail, it updates the event as processed.
You have multiple options for background processing:
Windows Service
In proc timer with a threadpool to process (only do this if you have one AT)
Worker role in Azure
Sql Agent Job
Write a Windows service that polls the database at a set amount of time (I'd say a little less than the minimum length of an auction. For an example, say a day). That service would store in memory actions that will end within that amount of time, and check every second whether there are actions that ended. For auctions that have ended, fire your CLOSE event.

displaying updation of data to multiple users which is inserted by another user

i need to show the updated data immediately to a user as he inputs into the database , i.e. online view.
i am using sql server and building a c# .net winform application.
the application would be used on LAN by 3 users, U1,U2,U3.
the users would input data into an ITEMS table using the application and as U2 clicks the insert button , he should view the updated data on the same Form at the bottom in a gridview or else , and also, U1,U3 would also automatically see the updated table on their PCs in the application.
how do i do this?
U1,U2,U3 have opened the application.
U2 has navigated to the INSERT items Form.
U1,U3 are on the view items Form.
i want that as U2 inserts data, then automatically the grid view on the application of U1,U3 is updated and they could see the new data inserted by U2 in the ITEMS table. they don't even need to refresh or reopen the view items Form.
Trigger have to be used on the ITEMS table. is there any way to avoid triggers here?
You do not need a trigger (at least not for the purpose described).
The common practice is to implement a refresh-on-demand capability (usually F5).
It is a bit absurd to keep the PCs or screens up-to-date with the database all the time. Consider the network traffic. Consider that no -one is there to read the screen when U1 or U2 answer the phone, go for lunch or a comfort break. A Refresh on demand capability is more reasonable.
Further, if you have to implement such a function, add a Last-Updated-TimeStamp or DateTime column to the table, and only retrieve the rows that have been updated since the last retrieval.
Response to Comments
Thanks.
On each table, include a Timestamp or Datetime column, named something like UpdatedDateTime. Set a default of GETDATE().
Update this column whenever you update the row.
Note that you can only meaningfully have one data window in focus, ie. in front, all other windows are out of focus, cannot be seen. So there is no point in coding the refresh or automatic refresh into every window; only those windows that actually need automatic refresh.
On the client or .NET side, for each window that needs refresh, write code for the Function-5 button. Whenever F5 is activated, refresh the window. That means:
fill your List Object (containing the logical data rows) for that window:SELECT column_list
FROM table t1
JOIN join_table t2 ...
WHERE t1.UpdatedDateTime > #SavedDateTime
OR t2.UpdatedDateTime > #SavedDateTime
... other_conditions
SET #SavedDateTime = GETDATE()
Paint the window
That will avoid moving masses of dat that do not change, across the network; and move only those rows that have changed into the window. An intelligent refresh.
Test that. Ensure that the manual refresh works as intended. Update the data on another PC, press F5 on this PC, and verify that the data in the window changes to reflect the updates; and that the window is now repainted when data does not change.
Now for the automatic refresh. Write an endless loop (always bad new), that waits 30 seconds, and executes the F5 button code. Now check that that works as intended.
If and when someone very senior wants their window refreshed more frequently (than 30 seconds), change that wait parameter to 15 seconds. If and when someone very senior wants their window refreshed more frequently (than 15 seconds), change that wait parameter to 10 seconds. Et cetera. Never set the wait to 1 or 2 or 5 seconds to begin with. And allow each PC to set its own wait period (big boss 5 seconds, little boss 30 seconds).
When the bosses wail about the network being slow, show them the packets that are flooding the network when no one is sitting in front of the PC to read the window, and suggest that they turn the Automatic Refresh off. The manual refresh remains available for anyone who is actually sitting in front of the window, whose fingers are not broken, to use.
you can do this by running a separate thread which will after a certain time span keep updating the data.
I would consider using to Event Notification/Service broker to notify clients of any data changes. No need to poll or refresh on the client.
And more detail on the blog of the Service Broker team

Categories

Resources