2006 - NRW Conf: Asynchronous asp.net

39
Copyright © 2006 newtelligence® AG | All rights reserved Asynchronous ASP.NET Daniel Fisher(lennybacon) Software Engineer newtelligence® AG

Transcript of 2006 - NRW Conf: Asynchronous asp.net

Copyright © 2006 newtelligence® AG | All rights reserved

Asynchronous ASP.NET

Daniel Fisher(lennybacon)Software Engineer

newtelligence® AG

Agenda

• Die Synchrone Welt?• Warum Asynchronität?• Asynchrone Programmierung

mit .NET• Asynchrone Web-Entwicklung• Asynchrone System-Architektur

Die Synchrone Welt?

• In der Programmierung „der erste Schritt“

• Stellen sie sich vor sie geben Ihre Steuererklärung ab… …und warten vor dem Zimmer bis sie ihren

Bescheid in der Hand halten?

• Synchronität in der „realen Welt“ … …eine Utopie

Warum Asynchronität?

• Weil nicht schlimmer ist als Warten

• In der Zeit, in der sie auf den Steuerbescheid warten… … führen sie ihr Leben schliesslich auch

weiter!

• Waruma also sollten ihre Applikationen warten? Auf eine Kalkulation, die Datenbank, den

Host, einen WebService …

Asynchrone Programmierung mit .NET

• Prerequisites Threads Timer Delegates

• IAsyncResult design pattern • AsyncCallbacks• Event-based Asynchronous Pattern

Threads• Synchroner Ablauf

• Asynchroner Ablauf*

*Parallele Abfolgen NUR auf Multiprozessor-Maschinen

Threads

• System.Threading.Thread Start() Sleep() Suspend() Resume() Interupt()

• Wirft Exception Abort()

• Wirft nicht abfangbare Exception• Thread-Objekt kann nicht weiterverwendet

werden

Threads

• Treads haben einen „Status“ Runnable

• Ready• Standby• Running

Not runnable• Transition• Waiting• Terminated

Threads

• Systemkonzept: Pro Prozeß ein ThreadPool Anforderungen an den Pool über eine

Warteschlange Muß eine Anforderung länger als eine

halbe Sekunde warten, wird neuer Pool-Thread erzeugt• Maximal 100 Threads• Wird Pool-Thread 30 Sekunden nicht

benötigt, wird Thread aus dem Pool entfernt

Threads• Ein Thread ist ein unabhängiger

Ausführungspfad innerhalb eines Prozesses Jeder Thread besitzt seinen eigenen Kontext

• Stack, Programmzähler, Register etc.

• Threads verrichten Arbeit Jeder Prozeß hat einen

• Kann aber beliebig viele haben

• Die Verteilung der Rechenzeit erfolgt auf Threadbasis

Threads

• Kommunikation zwischen Threads aufwendig Synchronisation ist schwierig Nur das Lesen und Schreiben von int ist

atomar Alles andere muß synchronisiert werden

Threads

• Synchronisation lock{}-Statement System.Threading.WaitHandle

• System.Threading.Mutex • System.Threading.AutoResetEvent • System.Threading.ManualResetEvent

System.Threading.Monitor System.Runtime.CompilerServices.

MethodImplAttribute System.Runtime.Remoting.Contexts.

SynchronisationAttribute

Threads

• Thread kann lokalen, eigenen Speicher haben Dynamisch: Thread Local Storage (TLS) Statisch: Thread-spezifische Felder

• Referenztypen möglich, aber problematisch!• Statischer Konstruktor läuft nur einmal

Threadsclass Class1{ [ThreadStatic] static int s_Amount

public void Book() { LocalDataStoreSlot dataSlot = Thread.GetNamedDataSlot("MyTlsSlot"); Thread.SetData(dataSlot, 10); Console.WriteLine( "Book amount for thread '{0}' = {1}", Thread.CurrentThread.Name, (int)Thread.GetData(dataSlot)); }}

Timer

• System.Threading.Timer Periodische Ausführung von

Funktionalität Status wird in übergebener Objekt-

Instanz gehalten Deinitialisierung mit Dispose()

Delegates

• Funktionszeiger• Basis für Events• Asynchrone Aufrufe möglich

IAsyncResult design pattern ...

IAsyncResult design pattern

• Implementierung mit je zwei Methoden BeginOperationName

• Startet die asynchrone Operation• Rückgabewert ist eine implementation von

IAsyncResult

EndOperationName• Beendet die asynchrone Operation• Rückgabewert ist der selbe wie bei der

entsprechenden synchronen Operation

IAsyncResult design pattern

• IAsyncResult hält Informationen über die asynchrone Operation AsyncState

• Optionaler applikations-spezifische Informationen

AsyncWaitHandle • Blockt den Zugriff auf Daten solange die Operation

läuft

CompletedSynchronously • Wurde die Operation auf dem aufrufenden Thread

beendet?

IsCompleted • Ist die Operation beendet?

AsyncCallback

• Eigene CallBack-Methode Aufruf nach Abschluss der asynchronen

Operation Methodensignatur definiert durch einen

delegateusing System.Runtime.InteropServices; namespace System{ // Summary: // References the callback method to be called when // the asynchronous operation is completed. [Serializable] [ComVisible(true)] public delegate void AsyncCallback(IAsyncResult ar);}

Event-based Asynchronous Pattern

• Implementierung mit zwei Methoden … OperationNameAsync

• Startet die asynchrone Operation

OperationNameAsyncCancel• Bricht die laufende Operation ab

• ... und einem Event OperationNameCompleted

• Feuert wenn die Operation abgeschlossen ist

Event-based Asynchronous Pattern• Benutzen

Objekt instanziieren Ereignissbehandlung and event

anhängen OperationNameAsync aufrufenusing System;

 namespace System.ComponentModel{ /// <summary>Represents the method that will handle the /// MethodNameCompleted event of an asynchronous operation. /// </summary> public delegate void AsyncCompletedEventHandler( object sender, AsyncCompletedEventArgs e);}

Asynchrone Web-Entwicklung• Asynchrone Methoden in der Web

Applikation aufrufen ASP.NET Async Pages ASP.NET Async Tasks

• RemoteScripting vs. AJAX ASP.NET Client Side Callbacks ASP.NET Atlas Framework

ASP.NET Async Pages• Page-Directive Attribute

• BeginEventHandler und/oder EndEventHandler mit AddOnPreRenderCompleteAsync registrierenBeginEventHandler bh = new BeginEventHandler(AsyncBeginPage);EndEventHandler eh = new EndEventHandler(AsyncEndPage);AddOnPreRenderCompleteAsync(bh, eh);

ASP.NET Async Tasks• Page-Directive Attribute

• BeginEventHandler und/oder EndEventHandler als Task mit RegisterAsyncTask registrieren

PageAsyncTask myTask = new PageAsyncTask(

AsyncBeginPage, AsyncEndPage,null, null);

RegisterAsyncTask(myTask);

ASP.NET Async …• Infastruktur zum „Einklinken“ von

ansynchron auszuführendem Code

• „Seamless integration“ of coding model Sieht aus wie Page_EventName Steht an der gleichen Stelle wie

Page_EventName Ist aber asynchron

• 7-10% Performancegewinn Durch „bessere Nutzung“ der Threads in

ThreadPool

The Web from the client side• Nach dem initialen Request/Response und

dem anzeigen der Seite wird bei jedem „Klick“ ein Request/Response ausgeführt.

• Im „Hintergrund“Daten übertragen.• Nur Daten übertragen die benötigt werden.

Keine Navigation, Grafiken oder Markup – Daten.

• Requirements: Scriptingfähigkeit des Browsers

RemoteScripting vs. AJAX• RemoteScripting

Ein Java Applet/ActiveX Control leitet clientseitige Anfragen an den Server• Nachteil: Java/ActiveX benötigt• Vorteil: Broadcast möglich

• AJAX Javascript: Events und XmlHttpRequests

• Vorteil: NUR Scriptingfähigkeit des Browsers• Nachteil:

– Keine „Events“ vom Server– Ugly Code...

AJAXvar request = new Request(); function _getXmlHttp(){ /*@cc_on @*/ /*@if (@_jscript_version >= 5)

var progids=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] or (i in progids) {

try { return new ActiveXObject(progids[i]) }catch (e) {}

} @end @*/ try { return new XMLHttpRequest();} catch (e2) {return null; }}

function Request() { this.Get = Request_get; this._get = _getXmlHttp(); if (this._get == null) return;}

...

AJAX...ReadyState = { Uninitialized: 0, Loading: 1, Loaded:2, Active:3, Completed: 4 }HttpStatus = { OK: 200, NotFound: 404 }

function Request_get(url, f_change, method) {if (!this._get) return;if (method == null) method="GET";if (this._get.readyState != ReadyState.Uninitialized)

this._get.abort() this._get.open(method, url, true);if (f_change != null)

var _get = this._get;this._get.onreadystatechange = function(){ f_change(_get);}

this._get.send(null);}

AJAX...function ajaxInnerHTML(method, args, elmId){ request.Get( url + "?m=" + escape(method) + "&p=" + escape(args),

function(result) { if (result.readyState!=ReadyState.Complete)

return;

if (result.status==HttpStatus.OK && result.responseText != "")

{ elm = document.getElementById(elmId); if(elm)

{ var response = result.responseText;

elm.innerHTML = response; } }

});}

AJAX

• Funktioniert nur mit „Ugly Hacks“ Oder nur mit einem Browser-Typ

• Javascript ist nicht typisiert• ...

• Codieren wie Ende der 90er?

Welcome to WEB 0.5?

ASP.NET ClientSideCallbacks<html xmlns="http://www.w3.org/1999/xhtml"><head id="Head" runat="server“><script type="text/ecmascript">function ReceiveServerData(rValue){ document.getElementById('Results').innerHTML = rValue; }</script></head><body> <form id="form1" runat="server“> <asp:ListBox ID="ListBox1" Runat="server“> <asp:ListItem Text="Cheese" Value="Cheese" /> </asp:ListBox><br />

Items in stock: <div id="Results" runat="server“ />

</form></body>

ASP.NET ClientSideCallbackspublic partial class _Default : Page, ICallbackEventHandler{ protected string returnValue; protected void Page_Load(object sender, EventArgs e) { string cb = Page.ClientScript.GetCallbackEventReference( this, "arg", “ReceiveServerData", ""); ListBox1.Attributes["onchange"] = cb.Replace(

"arg", "this.options[this.selectedIndex].text"); } public void RaiseCallbackEvent(string eventArgument){ returnValue = "10"; } public string GetCallbackResult(){ return returnValue; }

}

Atlas

• Eine Serverseitiges Framework für AJAX Plattform und Browser-Kompatibel Objektorientierte Serverseitige API Declaratives model

• Steuerelemente

Toolunterstützung für Designer und Entwickler

Kostenlos, Supported, Einfach zu benutzen

Atlas

• ASPX

• CodeBehind

<atlas:ScriptManager ID="sm1" runat="server" EnablePartialRendering="true" /><atlas:UpdatePanel ID="up1" runat="server"> <ContentTemplate> <asp:Button ID=“B" Text="GetData" runat="server" OnClick=“B_Click" /> <br /> <asp:Label ID="Message" runat="server" /> </ContentTemplate></atlas:UpdatePanel>

public partial class _Default : System.Web.UI.Page { protected void B_Click(object sender, EventArgs e) { Message.Text = "Button1 was clicked"; }}

Asynchrone System-Architekturen• Web-Server – Applikations-Server-Topologie

Synchron

Asynchron

• Entkoppelung durch MessageQueing

ASP.NET und MessageQueing

• Anfrage in RequestQueue schreiben• Warten auf eine Antwort:using (MessageQueue responseQueue = new MessageQueue(queuePath)){

responseQueue.MessageReadPropertyFilter.CorrelationId = true;  Message objMessage = responseQueue.ReceiveByCorrelationId( correlationId, new TimeSpan(0, 0, 0, timeOut), MessageQueueTransactionType.None);}

Fazit

Copyright © 2006 newtelligence® AG | All rights reserved

Copyright © 2006 newtelligence® AG | All rights reserved