Søg på DotNyt:
Denne blog er flyttet til www.nielsbrinch.com


lørdag den 12. april 2008

Trådning i ASP.NET

skrevet af Niels Brinch

Ja, der står ASP.NET. Trådning i .NET er rigtig let, men trådning i ASP.NET, det vil sige, på et website, er ikke helt så lige til at gøre på en god og pålidelig måde. Ikke fordi sproget eller miljøet gør det specielt besværligt, men fordi et website simpelt hen ikke er beregnet på det.

Anvendelse
Jeg har udviklet en funktion på et website hvor man kan hente oplysninger fra en web-adresse man indtaster. Oplysningerne står på siden efter indtastning og der skal også vises behandlede billeder fra web-adressen. Behandlingen af billeder tager meget længere tid end resten, hvorfor jeg vil gøre dette i en tråd, så brugeren kan se de første resultater med det samme. Et halvt minut senere er billederne klar og så vises de også på sitet.

1. UpdatePanel
Første ingrediens som skal bruges for at ovenstående kan lade sig gøre, er et UpdatePanel. Det er et panel som kommer med ASP.NET Ajax. Det er indbygget i Visual Studio 2008 men kan også hentes til Visual Studio 2005. I det panel kan placeres elementer som skal opdateres uden siden genindlæses. Her placerer jeg en Repeater som indeholder en skabelon til de billeder som lidt senere skal vises.

2. Timer
En timer er også en Ajax-kontrol. Den reagerer efter et bestemt interval. F.eks. hvert femte sekund. I dette tilfælde får det den effekt at siden holder øje med om tråden er færdig hvert femte sekund. Jeg anbefaler et minimum på 2 sekunder, da serveren jo skal kontaktes hver gang.

<asp:Timer Interval="3000" ID="imageTimer" runat="server" OnTick="imageTimer_Tick">
</asp:Timer>

3. Trigger
For at sikre mit UpdatePanel bliver opdateret, tilføjes en trigger til det.

Jeg har nu følgende:

<asp:UpdatePanel ID="imageUpdatePanel" runat="server" UpdateMode="Conditional">
  <Triggers>
    <asp:AsyncPostBackTrigger ControlID="imageTimer" EventName="Tick" />
  </Triggers>
  <ContentTemplate>
    -- her er min Repeater som indeholder billeder.
  </ContentTemplate>
</asp:UpdatePanel>

Bemærk UpdateMode="Conditional". Det betyder at panelet kun opdateres som følge af de triggere som er angivet.

4. Guid i ViewState
Da flere brugere kan anvende systemet på samme tid, skal vi have en mulighed for at vide hvilke tråde der hører til hvilke sider. Det gøres simpelt ved at skabe en guid og lægge den i ViewState. Som vist her:

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["guid"] = Guid.NewGuid().ToString();
}
}

5. Start af tråden
Ved start af tråden er det vigtigt at medsende ovennævnte guid så tråden senere kan informere korrekt om at den er færdig. Ved start af tråden skal også medsendes 'HttpContext.Current', eftersom tråden skal anvende oplysninger fra requestet. Navntlig skal den indbyggede Cache anvendes.


public static void BeginProcessImages(List<string> imageUrls, string guid)
{
ThreadParameter param = new ThreadParameter();
param.ImageUrls = imageUrls;
param.Guid = guid;
param.Context = HttpContext.Current;

ParameterizedThreadStart ts =
new ParameterizedThreadStart(ThreadedProcessImages);
Thread t = new Thread(ts);
t.Start(param);
}

private static void ThreadedProcessImages(object objParam)
{
ThreadParameter param = objParam as ThreadParameter;

string guid = param.Guid;
List<string> imageUrls = param.ImageUrls;
List<string> processedImageUrls = new List<string>();
Cache cache = param.Context.Cache;
    // Udførelse af arbejde her
}

6. Tråden færdigmelder sin opgave
Når tråden er færdig med sit arbejde, tilføjes resultatet af arbejdet til cachen med 'guid' som nøgle. Sådan:


cache.Add(guid, processedImageUrls, null, DateTime.Now.AddMinutes(10),
                Cache.NoSlidingExpiration, CacheItemPriority.High, null);

Desuden kan man f.eks. løbende opdatere en post under guid+"status" hvis man give mulighed for at brugergrænsefladen kan vise oplysninger om hvor langt arbejdet er undervejs. F.eks. i form af en progress bar.


7. Brugergrænsefladen opdateres
Til sidst skal vi kigge tilbage på brugergrænsefladen. Timeren vi tilføjede til brugergrænsefladen havde en event som hed Tick, som var bundet op til metoden "imageTimer_Tick". Det er i denne metode det kontrolleres om tråden er færdig. Når tråden er færdig, opdateres brugergrænsefladen med resultatet.


Herunder er hele metode. Bemærk at når tråden er færdig, bliver timeren sat til Enabled = false så den ikke længere udfører eventen.


protected void imageTimer_Tick(object sender, EventArgs e)
{
string guid = ViewState["guid"] as string;
if (Cache[guid] == null)
{
if (Cache[guid + "status"] != null)
{
string status = Cache[guid + "status"] as string;

lblWaitForUpdate.Text = "Please wait. " + status;
}
else
{
lblWaitForUpdate.Text += ".";
}
}
else
{
imageTimer.Enabled = false;

List<string> imageUrls = (List<string>)Cache[guid];
Cache.Remove(guid);

lblWaitForUpdate.Visible = false;
repImages.DataSource = imageUrls;
repImages.DataBind();
repImages.Visible = true;

btnSubmit.Enabled = true;
}
}

 


Ovenstående er én måde at lave en pålidelig trådning i en ASP.NET applikation med anvendelse af almindelige trygge komponenter og metoder. Fortæl gerne om andre måder at gøre det samme på i kommentarerne til dette indlæg.

0 kommentarer

0 Kommentarer:

Send en kommentar

<< Tilbage


 
Til forsiden

Niels Brinch