How to write the C# code to increment by 1 an item in Application state named “total” in ASP.net?
In order to modify any Application variables, you need to lock them before modifying it to ensure no inadvertent changes between parallel requests happen.
An example
Application.Lock();
var userCount = Convert.ToInt32(Application["OnlineUserCount"]);
Application["OnlineUserCount"] = ++userCount;
Application.UnLock();
Application.Lock ensures that only one thread or request has access to the variables and other requests wait in queue. You modify the values as per the need and Application.Unlock to release your lock so other requests can work on Application variables.
Please note that there may be a performance hit, if you depend on this!!
Note: A page does not need to lock the application object to edit the
application collection. If one page tries to edit the application
collection without locking and a second page also tries to edit the
collection, no error is sent by IIS and the Application object ends up
in an inconsistent state.
Better use a
static variable
and
Interlocked.Increment
like this:
private static int total= 0;
public static void Increment()
{
Interlocked.Increment(ref total);
}
Related
I was wondering if it is possible if it is possible to create background tasks, what I mean is, in asp.net every user has his own instance so if I was to create a timer, when 2 users are on it will create 2 instances of a timer which I don't want.
I basically want a timer that is one instance and is independent. The reason I want to do this is because I want to do a SQL query every 5 minutes or so, and I don't want 2 users running it at the same time because then it wouldn't be 5 minutes apart it could be 2 mins and 30 secs apart.
USER1 --- ASP.NET INSTANCE
USER2 --- ASP.NET INSTANCE
TIMER --- NOTHING TO DO WITH USERS
I have hear of things like web services and Quartz.net but I am unsure that it is what I want.
Hopefully it makes sense :)
Actually, Quartz.NET is the best solution because it's made for it: running tasks on a scheduled basis.
If, for some reasons, you don't want to use it, the simplest way is to use a Timer object inside a singleton class; you can start the timer in your global.asax and this will provide you with a single timer that will be shared between all your users.
Something like:
public class SingletonTimer
{
private static SingletonTimer _instance = null;
private Timer _myTimer;
protected SingletonTimer()
{
_myTimer = new Timer(Callback, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
}
private void Callback(object state)
{
// SQL QUERY
}
public static SingletonTimer GetInstance()
{
return _instance ?? (_instance = new SingletonTimer());
}
}
This is however a not stable solution because after 20 minutes of inactivity IIS will kill your pool and and the timer will stop running; the best thing to do is to host a Quart.NET scheduler in a different process, like a windows service.
In my page1.aspx i am generating a report from database by using thread.
//on button click
Hashtable ht = (Hashtable)Session["ReportParam"];
ReportThreadClass rth = new ReportThreadClass(ht);
Thread thread = new System.Threading.ThreadStart(rth .Run);
thread.Start();
In my thread class's rum method i am updating values in Hashtable that how many pages i have created.
//in thread' method
public virtual void Run()
{
int pagecount=0;
while(done)
{
//loading data from DB and generating html pages
ht["Total_Pages"] = pagecount;
}
}
At my Page2.aspx i am reading values from Session Variable
Hashtable ht = (Hashtable)Session["ReportParam"];
int TotalPages = (int) ht["Total_Pages"];
When i run above code in InProc mode every thing is working fine i am getting updated values from session.
Because every thing is stored in static variable, and ht is referenced by Session so it automatically get updated in session (HashTable not needed to reassign it to session back).
But when i run code in State server (OutProc mode) It need to store session data in different process by Serializing Hash-table.
But the value of Total_Pages is not getting updated in Page2.aspx even after Thread run completely.
So is there any event or method which get fired to store all updates in session variable to State-Server , if yes then pls tell me . if not then pls suggest me some idea to get updated value in page2.aspx.
I would explictely SET and GET SessionState like so:
In your thread Run
// no complex object like hastable, just a plain value...
Session["pageCount"] = pageCount;
In your page2.apsx:
var pageCount = (int) Session["pageCount"]??0;
The reason your report thread is not updating it's session value when using out-of-proc sessionstate is because the session has no way to detect the hashtable has a changed value, therefor it doesn't update the underlying storew with the serialized version of the hastable. When you explicity store one immutable object it will persist one it's value changed;
As the session might already be gone when your thread finishes a begtter option is to get hold of a reference to SqlSessionStateStore and call SetAndReleaseItemExclusive. Ultimately you might want to have an overloaded SessionStateProvider that can handle your scenario.
In Out Proc Mode Session is saved after some event so if your thread is updating your session variables then it won't persist in storage.
If u are using Inproc Mode then session store in Static Dictionary so if your thread updating it, u will get updated value to any page.
So u have two solutions for this situation
Use inProc mode
Maintain a dictionary in your thread class with key as Session id and value is your hash-table, So if page2.aspx wants to read value of hash-table then it will pass his session id to method and which will return required value.
Less efficient but I'd probably just ping the database for the page count on Page2.
Or create a separate session value for the page count on Page1, at the same time as doing everything else. (EDIT: Nevermind the second part, that's what Rene suggested below).
I have a web site which makes frequent requests to an external web service, and I'd like these calls to be async and parallel to avoid blocking and to speed up the site a bit. Basically, I have 8 widgets, each of which has to make its own web call(s).
For some reason, only the first 3 or so of them truly load async, and then the threads don't free up in time, and the rest of the widgets load sequencially. If i could get 3 of them to load in parallel, then 3 more in parallel, then 2 more in parallel, i'd be happy. So the issue is really that the threads aren't freeing up in time.
I'm guessing the answer has to do with some IIS configuration. I'm testing on a non-server OS, so maybe that's part of it.
Edit for #jon skeet:
I'm using reflection to invoke the web calls like this:
output = methodInfo.Invoke(webservice, parameters);
The widget actions (which eventually call the web service) are called via a jquery $.each() loop and the .load function (maybe this causes a bottleneck?). The widget actions are set up as async methods in an async controller.
Here is the code for one of the async methods (they are all set up like this):
public void MarketTradeWidgetAsync()
{
AsyncManager.OutstandingOperations.Increment();
//a bunch of market trade logic
//this eventually calls the web service
PlanUISetting uiSettingMarketQuotesConfig = WebSettingsProviderManager.Provider.GetMarketQuotes(System.Configuration.ConfigurationManager.AppSettings["Theme"], SessionValues<String>.GlobalPlanID, SessionValues<String>.ParticipantID, "MARKETQUOTES");
AsyncManager.OutstandingOperations.Decrement();
}
public ActionResult MarketTradeWidgetCompleted(MarketTradeTool markettradetool)
{
if (Session.IsNewSession)
return PartialView("../Error/AjaxSessionExpired");
else
{
ViewData["MarketData"] = markettradetool;
return PartialView(markettradetool);
}
}
And, like I said, these methods are called via jquery. My thinking is that since the action methods are async, they should give control back to the jquery after they get called, right?
SessionState = "readonly" for the page at hand fixed this issue. Evidently session locking was the issue.
I've got quite a lot of code on my site that looks like this;
Item item;
if(Cache["foo"] != null)
{
item = (Item)Cache["foo"];
}
else
{
item = database.getItemFromDatabase();
Cache.insert(item, "foo", null, DateTime.Now.AddDays(1), ...
}
One such instance of this has a rather expensive getItemFromDatabase method (which is the main reason it's cached). The problem I have is that with every release or restart of the application, the cache is cleared and then an army of users come online and hit the above code, which kills our database server.
What is the typical method of dealing with these sorts of scenarios?
You could hook into the Application OnStart event in the global.asax file and call a method to load the expensive database calls in a seperate thread when the application starts.
It may also be an idea to use a specialised class for accessing these properties using a locking pattern to avoid multiple database calls when the initial value is null.
I was wondering how TransactionScope class works to keep the transaction between different method calls (without the need to pass it as a parameter) and I came to this doubt. I've got two considerations about this question:
1
Looking into TransactionScope's implementation through Telerik JustDecompile, I've found that the current transaction is stored in a ThreadStatic member of the System.Transactions.ContextData class (code below).
internal class ContextData
{
internal TransactionScope CurrentScope;
internal Transaction CurrentTransaction;
internal DefaultComContextState DefaultComContextState;
[ThreadStatic]
private static ContextData staticData;
internal WeakReference WeakDefaultComContext;
internal static ContextData CurrentData
{
get
{
ContextData contextDatum = ContextData.staticData;
if (contextDatum == null)
{
contextDatum = new ContextData();
ContextData.staticData = contextDatum;
}
return contextDatum;
}
}
public ContextData()
{
}
}
The CurrentData property is called by TransactionScope's PushScope() method, and the last one is used by most of the TransactionScope constructors.
private void PushScope()
{
if (!this.interopModeSpecified)
{
this.interopOption = Transaction.InteropMode(this.savedCurrentScope);
}
this.SetCurrent(this.expectedCurrent);
this.threadContextData.CurrentScope = this;
}
public TransactionScope(TransactionScopeOption scopeOption)
{
// ...
this.PushScope();
// ...
}
Ok, I guess I've found how they do that.
2
I've read about how bad is to use ThreadStatic members to store objects within ASP.NET (http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx) due the ASP.NET thread switching that might occur, so this data can be lost among the worker threads.
So, it looks like TransactionScope should not work with ASP.NET, right? But as far I have used it on my web applications, I don't remember any problem that I've run into about transaction data being lost.
My question here is "what's the TransactionScope's trick to deal with ASP.NET's thread switching?".
Did I make a superficial analysis on how TransactionScope stores its transaction objects? Or TransactionScope class wasn't made to work with ASP.NET, and I can be considered a lucky guy that never had any pain about it?
Could anyone who knows the "very deep buried secrets" of .NET explain that for me?
Thanks
I believe ASP.NET thread switching happens only in specific situations (involving asych IO operations) and early in the request life cycle. Typically, once the control is passed to the actual http handler (for example, Page), thread does not get switched. I believe that in most of situation, transaction scope will get initialized only after that (after page_init/load) and should not be an issue.
Here are few links that might interest you:
http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html
http://piers7.blogspot.com/2005/12/log4net-context-problems-with-aspnet.html