Risipa de key_press | Programare

Programare .Net | Tehnici de programare | Tutoriale | Lectii si exemple

Risipa de key_press | Programare - Programare .Net | Tehnici de programare | Tutoriale | Lectii si exemple

Fire de executie in Asp.Net

Zilele trecute am avut nevoie sa scriu un modul pentru o aplicatie asp.Net care sa ruleze in background. Executia codului respectiv este declansata in metoda Application_Start, metoda din Global.asax.

Ceea ce aveam de facut in background era sa pun in Cache cateva date obtinute de la un webservice lent. Pare simplu, nu? Asa am crezut si eu. Insa am aflat ca daca intr-un thread separat se apeleaza HttpContext.Curent, acesta este null.

Sa presupunem ca avem urmatorul cod:

    private void BuildCache()
    {
        string[] ids = new string[] { "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10" };
        System.Threading.Thread wt = new System.Threading.Thread(BgWorker);
        wt.Start(ids);
    }

    private void BgWorker(object pars)
    {
        string[] ids = pars as string[];
        foreach (string id in ids)
        {
            //some long time operation
            if (HttpContext.Current.Cache[id]==null)
                HttpContext.Current.Cache.Add(id, "Result of procesing: " + id, null, DateTime.Now.AddHours(24), new TimeSpan(24, 0, 0), System.Web.Caching.CacheItemPriority.Normal, null);
        }
    }

some long time operation e locul unde se apeleaza webservice-ul care raspunde greu sau orice alt cod care are nevoie de mult timp pentru a fi executat. Am scos codul propriu-zis pentru ca nu e relevant in exemplu.

Acest cod va arunca o exceptie in linia in care verific HttpContext.Current.Cache[id]==null. Exceptia care apare e data de faptul ca HttpContext.Current este null. Si este null pentru ca acum sunt intr-un thread separat de threadul principal al aplicatiei. Nu am cautat explicatii mai detaliate, am luat situatia ca atare si am cautat solutii. Solutia pe care am gasit-o a fost sa trimit o referinta la Cache din thread-ul principal in threadul de fundal. Asta se face asa:

    private void BuildCache()
    {
        string[] ids = new string[] { "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10" };
        System.Threading.Thread wt = new System.Threading.Thread(BgWorker);
        object[] o = new object[] { ids, HttpContext.Current.Cache }; //construiesc un obiect pe care il trimit in bg worker
        wt.Start(o);
    }

    private void BgWorker(object pars)
    {
        object[] o = pars as object[];  //am primit aici tot ce imi trebuie din threadul principal

        string[] ids = o[0] as string[];
        System.Web.Caching.Cache cache = o[1] as System.Web.Caching.Cache;
        foreach (string id in ids)
        {
            //some long time operation
            if (cache[id] == null)
                cache.Add(id, "Result of procesing: " + id, null, DateTime.Now.AddHours(24), new TimeSpan(24, 0, 0), System.Web.Caching.CacheItemPriority.Normal, null);
        }
    }

Si asa a mers.

Problema urmatoare pe care trebuie sa o rezolv este ca trebuie sa dezvolt aplicatia si sa folosesc cod compilat intr-un dll unde, hardcoded, folosesc HttpContext.Current. Se pare ca nu o sa am de ales si o sa trebuiasca sa corectez/completez dll ul respectiv, ceea ce, trebuie sa recunosc, nu e deloc ceva ce imi face placere.

Sfat: daca scrieti librarii aditionale aplicatiilor web pe care le faceti, nu folositi niciodata in inteiorul acelui dll HttpContext.Current. In schimb trimiteti clasei din interiorul dll-ului o referinta la HttpContext.Current. Sau cel putin lasati optiunea asta:

public class ClasaDinDll
{
    public System.Web.HttpContext Context { get; set; }

    public void Metoda()
    {
        System.Web.HttpContext workContext = HttpContext.Current;
        if (workContext == null)
            workContext = Context;

        //cod in continuare....
    }
}
Category: Uncategorized
  • Octav says:

    Pentru Cache poti folosi si HttpRuntime.Cache si este independent de HttpContext.Current.

    October 24, 2012 at 3:39 pm

Your email address will not be published. Required fields are marked *

*