2006 - NRW Conf: Asynchronous asp.net
-
Upload
daniel-fisher -
Category
Software
-
view
45 -
download
1
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);}