Task-based Asynchronous Programming

Download Report

Transcript Task-based Asynchronous Programming

Krótka historia
asynchroniczności w .NET 1-4.5
Jakub Binkowski
O mnie


Jakub Binkowski
Senior .NET Developer @ Rule Financial

Microsoft MVP w latach 2008-2011
MCP, MCTS, MCPD

Lider Łódzkiej Grupy Profesjonalistów IT & .NET

[email protected]

Agenda


Dlaczego asynchroniczność?
Jak?






Asynchronous Programming Model (APM)
Event-based Asynchronous Pattern (EAP)
Task-based Asynchronous Pattern (TAP)
Async i await w .NET 4.5
Asynchroniczny ASP.NET
Testy jednostkowe
Dlaczego asynchroniczność?
Przypomnienie: Wątek jest drogi

Pamięć:


ponad 1MB (pamięć zarezerwowana)
Czas:


Powiadomienia o utworzeniu i zamknięciu wątku
(do wszystkich DLL)
Przełączenia kontekstu
Przypomnienie: Pula wątków

Zbiór wątków dostępnych dla aplikacji
Jedna na proces (CLR)

Ilość wątków w puli





Minimalna ilość wątków = ilość procesorów logicznych
Maksymalna – zależy od środowiska
Algorytm – czarna skrzynka
Klasa ThreadPool
Przykład 1 – ASP.NET
Przykład 1 – ASP.NET
public ActionResult AvatarDetails()
{
var url = "http://...";
var data = new WebClient().DownloadData(url);
var bitmap = new Bitmap(new MemoryStream(data));
var model = new AvatarModel
{
AvatarUrl = url,
Size = data.Length,
Width = bitmap.Width,
Height = bitmap.Height
};
return View(model);
}
Gdzie jest problem?


Pula wątków obsługujących żądania
Dla uproszczenia – pula = 3 wątki; 3 procesory
Web
Service
DB
HTML
HTML
Web
Service
HTML
CPU = 66%
Gdzie jest problem?


Pula wątków obsługujących żądania
Dla uproszczenia – pula = 3 wątki; 3 procesory
HTML
HTML
Web
Service
DB
HTML
Web
Service
CPU = 33%
Gdzie jest problem?


Pula wątków obsługujących żądania
Dla uproszczenia – pula = 3 wątki; 3 procesory
HTML
HTML
HTML
Web
Service
DB
Web
Service
CPU = 0%
!
Operacje obliczeniowe
Wątek
Operacje I/O (synchroniczne)
Wątek
Operacja I/O
Urządzenie
Gdyby…

1 cykl procesora = 1 sekunda:




Rejestr: 1s
Pamięć: 5-10s
Dysk: 3 miesiące
Sieć: 30 lat
Przykład 2 - WPF
Przykład 2 - WPF
void Button_Click(object sender, RoutedEventArgs e)
{
var data = new WebClient().DownloadData(tbUrl.Text);
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = new MemoryStream(data);
bitmap.EndInit();
imgAvatar.Source = bitmap;
}
Uwaga!
Brzydki
kod
Przykład 2 – WPF (aplikacja desktop)


Tylko jeden wątek obsługuje UI
W czasie wykonywania operacji aplikacja nie odpowiada
Programowanie synchroniczne
Problemy

Problem 1:
Pula wątków blokowana przez zewnętrzne urządzenia
(I/O)

Problem 2:
Wątek UI zajęty przez długotrwałą operację
Wzorce asynchroniczne
APM vs EAP vs TAP
Kod synchroniczny

API:
public interface IMyType
{
int DoSomething(int a);
}

Wywołanie:
IMyType type = /*..*/;
int result = type.DoSomething(10);
Asynchronous Programming Model
API
public interface IMyType
{
IAsyncResult BeginDoSomething(int a,
AsyncCallback callback, object state);
int EndDoSomething(IAsyncResult asyncResult);
}
Asynchronous Programming Model
Użycie – wariant 1
IMyType type = /*..*/;
IAsyncResult asyncRes = type.BeginDoSomething(10, null, null);
//...
int result = type.EndDoSomething(asyncRes);
//...
Asynchronous Programming Model
Użycie – wariant 2
class MyProgram
{
private IMyType _type;
public void Begin()
{
_type.BeginDoSomething(10, OnDoSomethingFinished, null);
}
private void OnDoSomethingFinished(IAsyncResult asyncRes)
{
int result = _type.EndDoSomething(asyncRes);
//...
}
}
Asynchronous Programming Model
Użycie – wariant 2b
IMyType type = /*..*/;
type.BeginDoSomething(10,
asyncRes =>
{
int result = type.EndDoSomething(asyncRes);
//...
},
null);
Demo
Asynchronous Programming Model
Trochę historii


Oryginalnie IAsyncResult jedynym wzorcem
Wg zespołu Windows Forms IAsyncResult jest




zbyt skomplikowany
nie pasuje do trybu design
wymaga pilnowania wątków
Efekt – alternatywne podejście:
Event-base Asynchronous Programming
Event-based Asynchronous Programming
API
public interface IMyType
{
void DoSomethingAsync(int a);
event DoSomethingCompletedEventHandler DoSomethingCompleted;
}
public class DoSomethingCompletedEventArgs: AsyncCompletedEventArgs
{
public int Result { get; set; } /*…*/
}
public delegate void DoSomethingCompletedEventHandler(
object sender, DoSomethingCompletedEventArgs args);
Event-based Asynchronous Programming
Użycie
IMyType type = /*...*/;
type.DoSomethingCompleted += (sender, args) =>
{
int result = args.Result;
//...
};
type.DoSomethingAsync(10);
Demo
Event-based Asynchronous Programming
APM
Zastosowanie

FCL: 60 klas

Strumienie (System.IO.Stream)
DNS (System.Net.Dns)
Gniazda sieciowe (System.Net.Sockets.Socket)
Żądania sieciowe (System.Net.WebRequest)
Polecenia SQL (System.Data.SqlClient.SqlCommand)
Porty (System.IO.Ports.SerialPort)
Web/Service References






EAP
Zastosowanie

FCL: 17 klas


System.ComponentModel.BackgroundWorker;
System.Net.WebClient;
System.Net.NetworkInformation.Ping;
System.Windows.Forms.PictureBox;
System.Net.Mail.SmtpClient;

i inne…



APM czy EAP?
Gdzie jest problem?

Gdzie jest problem?

W drodze ku lepszemu

.NET 4.0 wprowadził nowy model programowania
równoległego – Task Parallel Library

C# 4.5 wprowadzi nowy model programowania
asynchronicznego:
Task-based Asynchronous Programming

APM i EAP staną się przestarzałe
Idea TAP


Niech deweloperzy piszą kod
prawie tak samo
„Magią” niech zajmie się kompilator
Task-based Asynchronous Programming
API
public interface IMyType
{
Task<int> DoSomethingTask(int a);
}
Task-based Asynchronous Programming
API
public interface IMyType
{
Task<int> DoSomethingTask(int a);
}
Task-based Asynchronous Programming
Użycie
public async Task<bool> IsSomethingZeroAsync(int a)
{
IMyType type = /*...*/;
var value = await type.DoSomethingAsync(a);
return value == 0;
}
Task-based Asynchronous Programming
Użycie
public async Task<bool> IsSomethingZeroAsync(int a)
{
IMyType type = /*...*/;
var value = await type.DoSomethingAsync(a);
return value == 0;
}
Task-based Asynchronous Programming
Użycie
public async Task<bool> IsSomethingZeroAsync(int a)
{
IMyType type = /*...*/;
var value = await type.DoSomethingAsync(a);
return value == 0;
}
Task-based Asynchronous Programming
Użycie
public async Task<bool> IsSomethingZeroAsync(int a)
{
IMyType type = /*...*/;
var value = await type.DoSomethingAsync(a);
return value == 0;
}
Demo
Task-based Asynchronous Programming
ASP.NET
Asynchroniczne ASP.NET MVC 3 i 4
Demo
ASP.NET MVC 3
Synchroniczny kontroler
ASP.NET MVC 3
public class HomeController : Controller
{
public ActionResult AvatarDetails()
{
var client = new WebClient();
var data = client.DownloadData(new Uri("…"));
//...
return View();
}
}
Asynchroniczny kontroler
ASP.NET MVC 3
public class HomeController : AsyncController
{
public void AvatarDetailsAsync()
{
AsyncManager.OutstandingOperations.Increment();
var client = new WebClient();
client.DownloadDataCompleted += (s, a) =>
{
AsyncManager.Parameters["data"] = a.Result;
AsyncManager.OutstandingOperations.Decrement();
};
client.DownloadDataAsync(new Uri("…"));
}
public ActionResult AvatarDetailsCompleted(byte[] data)
{
//...
return View();
}
}
Asynchroniczny kontroler
ASP.NET MVC 3
public class HomeController : AsyncController
{
public void AvatarDetailsAsync()
{
AsyncManager.OutstandingOperations.Increment();
var client = new WebClient();
client.DownloadDataCompleted += (s, a) =>
{
AsyncManager.Parameters["data"] = a.Result;
AsyncManager.OutstandingOperations.Decrement();
};
client.DownloadDataAsync(new Uri("…"));
}
public ActionResult AvatarDetailsCompleted(byte[] data)
{
//...
return View();
}
}
Asynchroniczny kontroler
ASP.NET MVC 3
public class HomeController : AsyncController
{
public void AvatarDetailsAsync()
{
AsyncManager.OutstandingOperations.Increment();
var client = new WebClient();
client.DownloadDataCompleted += (s, a) =>
{
AsyncManager.Parameters["data"] = a.Result;
AsyncManager.OutstandingOperations.Decrement();
};
client.DownloadDataAsync(new Uri("…"));
}
public ActionResult AvatarDetailsCompleted(byte[] data)
{
//...
return View();
}
}
Asynchroniczny kontroler
ASP.NET MVC 3
public class HomeController : AsyncController
{
public void AvatarDetailsAsync()
{
AsyncManager.OutstandingOperations.Increment();
var client = new WebClient();
client.DownloadDataCompleted += (s, a) =>
{
AsyncManager.Parameters["data"] = a.Result;
AsyncManager.OutstandingOperations.Decrement();
};
client.DownloadDataAsync(new Uri("…"));
}
public ActionResult AvatarDetailsCompleted(byte[] data)
{
//...
return View();
}
}
Demo
ASP.NET MVC 4 + async
Synchroniczny kontroler
ASP.NET MVC 4
public class HomeController : Controller
{
public ActionResult AvatarDetails()
{
var client = new WebClient();
var data = client.DownloadData(new Uri("…"));
//...
return View();
}
}
Asynchroniczny kontroler
ASP.NET MVC 4
public class HomeController : AsyncController
{
public async Task<ActionResult> AvatarDetails()
{
var client = new WebClient();
var data = await client.DownloadDataTaskAsync(new Uri("…"));
//...
return View();
}
}
Asynchroniczny kontroler
ASP.NET MVC 4
public class HomeController : AsyncController
{
public async Task<ActionResult> AvatarDetails()
{
var client = new WebClient();
var data = await client.DownloadDataTaskAsync(new Uri("…"));
//...
return View();
}
}
Asynchroniczny kontroler
ASP.NET MVC 4
public class HomeController : AsyncController
{
public async Task<ActionResult> AvatarDetails()
{
var client = new WebClient();
var data = await client.DownloadDataTaskAsync(new Uri("…"));
//...
return View();
}
}
„async” a testy jednostkowe
Demo
Synchronous unit tests
Demo
Asynchronous unit tests
Podsumowanie

3 wzorce programowania asynchronicznego:




TAP zastępuje APM i EAP




APM (Asynchronous Programming Model)
EAP (Event-based Asynchronous Programming)
TAP (Task-based Asynchronous Programming)
nowe metody w całym .NET Framework
wsparcie w ASP.NET
wsparcie w WCF
Potężne wsparcie kompilatora – async i await
Przydatne odnośniki



http://www.albahari.com/threading/
Asynchronous programming design patterns:
http://msdn.microsoft.com/en-us/library/ms228969.aspx
Asynchronous ASP.NET:



http://msdn.microsoft.com/en-us/magazine/cc163725.aspx
http://msdn.microsoft.com/en-us/library/ee728598.aspx
Asynchronous WCF:
http://msdn.microsoft.com/en-us/library/ms734701.aspx
Przydatne odnośniki – „async”




TAP in-depth:
http://www.microsoft.com/download/en/details.aspx?id=1
9957
Visual Studio 11 CTP:
http://www.microsoft.com/download/en/details.aspx?displ
aylang=en&id=27543
ASP.NET MVC 4 CTP:
http://www.microsoft.com/web/gallery/install.aspx?appid=
MVC4VS11&prerelease=true
Jon Skeet blog: http://msmvps.com/blogs/jon_skeet/
Dziękuję za uwagę.
Pytania?