SlideShare une entreprise Scribd logo
1  sur  23
.NET Web プログラミングにおける
非同期 I/O のすべて
日本マイクロソフト株式会社
エバンジェリスト
松崎 剛
http://blogs.msdn.com/b/tsmatsuz
2
セッション ゴール
• .NET Web 開発における非同期 IO の基本を学ぶ
発想の原点や歴史、基本メカニズム、用語などについて
• べし・べからず、Tips、などを理解
新機能にはワケがある !
~ スケーラブルな Web を作ろう ~
3
非同期のプログラミング・パターン
• EAP (Event-based Asynchronous Pattern)
• APM (Asynchronous Programming Model)
• TAP (Task-based Asynchronous Pattern)
FileStream fs;
byte[] readArray = new byte[0x1000];
. . .
fs.BeginRead(readArray, 0, readArray.Length,
new AsyncCallback(readCallback), fs);
. . .
private void readCallback(IAsyncResult ar)
{
System.IO.FileStream fs =
(System.IO.FileStream)ar.AsyncState;
int fsize = fs.EndRead(ar);
. . .
}
MyReadClass myRead = new MyReadClass();
myRead.ReadCompleted +=
new EventHandler<ReadCompletedEventArgs>(
readCompleted);
myRead.ReadAsync();
. . .
private void readCompleted(
object sender, ReadCompletedEventArgs e)
{
var res = e.Result;
. . .
}
using (StreamReader reader = File.OpenText(filename))
{
result = new char[reader.BaseStream.Length];
Task<int> t = reader.ReadAsync(result, 0, (int) reader.BaseStream.Length);
}
4
ASP.NET における非同期の変遷
ASP.NET Web フォーム ASP.NET MVC
.NET 2.0
.NET 3.5
.NET 4.5
.NET 4.0
5
プログラミング・パターンの相性
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.PreRenderComplete +=
new EventHandler(Page_PreRenderComplete);
AddOnPreRenderCompleteAsync(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation));
}
}
IAsyncResult BeginAsyncOperation(object
sender, EventArgs e, AsyncCallback cb, object state)
{
_connection = new SqlConnection(connectstring);
_connection.Open();
_command = new SqlCommand(
"SELECT title_id, title, price FROM titles",
_connection);
return _command.BeginExecuteReader(cb, state);
}
void EndAsyncOperation(IAsyncResult ar)
{
_reader = _command.EndExecuteReader(ar);
}
protected void Page_PreRenderComplete(object
sender, EventArgs e)
{
Output.DataSource = _reader;
Output.DataBind();
}
ASP.NET Async Page (APM)
+
DB Access (APM)
6
TAP + async/await (C# 5.0)
public Task<ActionResult> Test1()
{
// Step 1
HttpClient cl = new HttpClient();
Task<HttpResponseMessage> task = cl.GetAsync(@"http://heavyweb.cloudapp.net/");
return task.ContinueWith(t =>
{
// Step 2
ViewBag.ResultData = t.Result.ToString();
return (ActionResult)View();
});
}
public async Task<ActionResult> Test1()
{
// Step 1
HttpClient cl = new HttpClient();
HttpResponseMessage result = await cl.GetAsync(@"http://heavyweb.cloudapp.net/");
// Step 2
ViewBag.ResultData = result.ToString();
return (ActionResult)View();
}
7
ASP.NET における非同期
要求 (Request)、キュー (Queue)、スレッド (Thread)
Web サーバー (IIS)
要求 (Request)
キュー (Queue)
処理中 …
処理中 …
処理中 …
スレッド (Thread)
スレッド プール
8
ASP.NET における非同期
同期のケース
お医者さん
=
スレッド (Thread)
患者さん
=
要求 (Request)
受付
=
キュー (Queue)
9
ASP.NET における非同期
同期のケース
10
ASP.NET における非同期
同期のケース
空くのを待機 . . .
11
ASP.NET における非同期
非同期のケース
12
ASP.NET における非同期
非同期のケース
13
ASP.NET における非同期
非同期のケース
14
I/O Completion Port (IOCP)
• Windows が提供する機構
• 1 つの IOCP は、1 つ以上のデバイス ハンドル (ファイル ハンドルな
ど) と関連
• キューのメカニズムを使って、非同期 IO の完了をプログラムから検知
• スレッドの状態 (待ち状態、リリース状態、など) を監視し、スレッド
の実行数を自動で制御
• IOCP でブロックされたスレッドは、いったん解放されて、LIFO の
キューに入る (1 つのスレッドが継続して処理可能。可能な限り
Context Switch を抑制)
• Win32 API を提供
• カスタムな制御が可能
• Thread Pool API を使った I/O 処理、Timer処理 (Thread Pool Timer)
で使用
15 15
16 16
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.IsWebSocketRequest)
{
BetsHandler1 handler = new BetsHandler1();
context.AcceptWebSocketRequest(handler.Receive);
}
else
{
context.Response.StatusCode = 400; //bad request
}
}
. . .
}
public class BetsHandler1
{
public WebSocket webSocket;
public async Task Receive(
AspNetWebSocketContext context)
{
webSocket = context.WebSocket;
ArraySegment<byte> buf =
new ArraySegment<byte>(new byte[2048]);
while (true)
{
WebSocketReceiveResult res =
await webSocket.ReceiveAsync(
buf,
System.Threading.CancellationToken.None);
if (res.MessageType ==
WebSocketMessageType.Close)
{
// Close Message
connectedHandlers.Remove(this);
await webSocket.CloseOutputAsync(
. . .);
break;
}
else if (res.MessageType ==
WebSocketMessageType.Text)
{
// Text Message
. . . Some kind of process
}
}
}
. . .
}
17 17
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.IsWebSocketRequest)
{
BetsHandler1 handler = new BetsHandler1();
context.AcceptWebSocketRequest(handler.Receive);
}
else
{
context.Response.StatusCode = 400; //bad request
}
}
. . .
}
public class BetsHandler1
{
public WebSocket webSocket;
public Task Receive(
AspNetWebSocketContext context)
{
webSocket = context.WebSocket;
ArraySegment<byte> buf =
new ArraySegment<byte>(new byte[2048]);
while (true)
{
WebSocketReceiveResult res =
webSocket.ReceiveAsync(
buf,
System.Threading.CancellationToken.None);
if (res.MessageType ==
WebSocketMessageType.Close)
{
// Close Message
connectedHandlers.Remove(this);
webSocket.CloseOutputAsync(
. . .);
break;
}
else if (res.MessageType ==
WebSocketMessageType.Text)
{
// Text Message
. . . Some kind of process
}
}
return new TaskFactory().StartNew(() => { });
}
. . .
}
18
.NET 4.5 Web の TAP 対応 (“呼ぶ” 側)
• ASP.NET Web フォーム
• ASP.NET Web API
• WCF
• WebSocket
. . .
protected void Page_Load(object sender, EventArgs e)
{
Page.RegisterAsyncTask(new PageAsyncTask(async () =>
{
HttpClient cl = new HttpClient();
HttpResponseMessage res =
await cl.GetAsync(@“http://.../");
Label1.Text = res.ToString();
}));
}
public class Service1 : IService1
{
public async Task<string> GetDataAsync()
{
HttpClient cl = new HttpClient();
HttpResponseMessage res =
await cl.GetAsync(@“http://.../");
return res.ToString();
}
}
public class ValuesController : ApiController
{
// GET api/values
public async Task<string> Get()
{
HttpClient cl = new HttpClient();
HttpResponseMessage res =
await cl.GetAsync(@"http://.../");
return res.ToString();
}
}
context.AcceptWebSocketRequest(handler.Receive);
. . .
public async Task Receive(AspNetWebSocketContext context)
{
while (true)
{
WebSocketReceiveResult res =
await context.WebSocket.ReceiveAsync(. . .);
. . .
}
}
19
IO リソースの TAP 対応 (“呼ばれる” 側)
ファイル入出力 .NET 4.5 で TAP (async) のメソッド (ReadAsync, WriteAsync,
CopyToAsync など) を提供 (これまでは、APM のみ)
データ
ベース
ADO.NET .NET 4.5 で TAP (async) のメソッド (ReadAsync など) を提供
(これまでは、APM のみ)
Entity
Framework
Entity Framework 6 で、TAP (async) をサポート
(現在、ベータ版を提供)
ネット
ワーク
REST HttpClient のメソッドは、基本的に TAP ベース
WCF .NET 4.5 で自動生成される Service Refrence Proxy では、TAP
(async) のメソッドを提供
クラウド Windows Azure
ServiceBus
最新の WindowsAzure.ServiceBus パッケージ (NuGet) で TAP の
メソッド (NamespaceManager.QueueExistsAsync など) を提供
(APM も使用可能)
では、未対応のものはどうする ?
(例 : WCF Data Services, Windows Azure Storage など)
ますます、対応中 . . . (こうご期待!)
20
SynchronizationContext
• スレッド間の関係を管理する抽象化されたスケジューラー・オブジェクト
 ASP.NET 非同期スレッドは、Win32 メッセージ ループのように特定スレッドに紐づかない
• 1 つのスレッドに対し、必ず 1 つの SynchronizationContext が存在 (ただし、単一
のSynchronizationContext は複数スレッドで共有)
• 一部の実装 (override メソッド) を除き、具体的な実装は派生クラスに依存
 WindowsFormsSynchronizationContext
 DispatcherSynchronizationContext
 AspNetSynchronizationContext
 既定の SynchronizationContext
• これまでの非同期処理 (EAP など) において、その動作をつかさどる
• TAP では TaskScheduler を使用 (SynchronizationContext を使用する際は、
TaskScheduler.FromCurrentSynchronizationContext を明示)
21
SynchronizationContext
• 既定の Awaiter (TaskAwaiter) は、Current の SynchronizationContext を使用
(なければ TaskScheduler も参照)
 AspNetSynchronizationContext では、同期ブロックに入れるスレッドは 1 つだけ
• .NET 4 以降では、Task と相性の良い新しい AspNetSynchronizationContext を使用
 従来のものは LegacyAspNetSynchronizationContext に変更
この場合でも、Web.configの設定で新しいContextを
使用可能
<appSettings>
<add
key="aspnet:UseTaskFriendlySynchronizationContext“
value="true"/>
</appSettings>
22
混ぜるな、危険 💀
• Async (EAP, TAP, etc) と Sync の混
在プログラムは、デッドロックの原因
となる !
Task で受け取った内容を、むりやり同期
化しない (All async is beautiful !)
「扱いやすい」(理解しやすい) という理
由だけで、 Result、Wait を多用しない
(初心者にありがちなミス)
現実の開発では、追跡とデバッグが非常に
困難 (例 : 単一では動作するんだけ
ど ?、コンソール・アプリでは動くのに ?
など)
.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)

Contenu connexe

Tendances

AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
Yoshifumi Kawai
 

Tendances (20)

AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
 
Deep Dive into the Linux Kernel - メモリ管理におけるCompaction機能について
Deep Dive into the Linux Kernel - メモリ管理におけるCompaction機能についてDeep Dive into the Linux Kernel - メモリ管理におけるCompaction機能について
Deep Dive into the Linux Kernel - メモリ管理におけるCompaction機能について
 
Lightweight Keycloak
Lightweight KeycloakLightweight Keycloak
Lightweight Keycloak
 
Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
 
20160526 依存関係逆転の原則
20160526 依存関係逆転の原則20160526 依存関係逆転の原則
20160526 依存関係逆転の原則
 
実践!Django + GraphQL 実装
実践!Django + GraphQL 実装実践!Django + GraphQL 実装
実践!Django + GraphQL 実装
 
3種類のTEE比較(Intel SGX, ARM TrustZone, RISC-V Keystone)
3種類のTEE比較(Intel SGX, ARM TrustZone, RISC-V Keystone)3種類のTEE比較(Intel SGX, ARM TrustZone, RISC-V Keystone)
3種類のTEE比較(Intel SGX, ARM TrustZone, RISC-V Keystone)
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
 
An Internal of LINQ to Objects
An Internal of LINQ to ObjectsAn Internal of LINQ to Objects
An Internal of LINQ to Objects
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ
 
PythonによるOPC-UAの利用
PythonによるOPC-UAの利用PythonによるOPC-UAの利用
PythonによるOPC-UAの利用
 
openstack+cephインテグレーション
openstack+cephインテグレーションopenstack+cephインテグレーション
openstack+cephインテグレーション
 
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
 
Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話
 

En vedette

よりよい開発を目指すための、プロセス&ツール活用
よりよい開発を目指すための、プロセス&ツール活用よりよい開発を目指すための、プロセス&ツール活用
よりよい開発を目指すための、プロセス&ツール活用
Kaoru NAKAMURA
 
50分で掴み取る ASP.NET Web API パターン&テクニック
50分で掴み取る ASP.NET Web API パターン&テクニック50分で掴み取る ASP.NET Web API パターン&テクニック
50分で掴み取る ASP.NET Web API パターン&テクニック
miso- soup3
 
Build Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るか
Build Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るかBuild Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るか
Build Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るか
H2O Space. Co., Ltd.
 
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例までBuildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Masahiro Wakame
 
スケーラビリティと耐障害性を両立するWeb アプリケーション
スケーラビリティと耐障害性を両立するWeb アプリケーションスケーラビリティと耐障害性を両立するWeb アプリケーション
スケーラビリティと耐障害性を両立するWeb アプリケーション
Masayoshi Hagiwara
 
HttpClient詳解、或いは非同期の落とし穴について
HttpClient詳解、或いは非同期の落とし穴についてHttpClient詳解、或いは非同期の落とし穴について
HttpClient詳解、或いは非同期の落とし穴について
Yoshifumi Kawai
 

En vedette (10)

非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
 
よりよい開発を目指すための、プロセス&ツール活用
よりよい開発を目指すための、プロセス&ツール活用よりよい開発を目指すための、プロセス&ツール活用
よりよい開発を目指すための、プロセス&ツール活用
 
50分で掴み取る ASP.NET Web API パターン&テクニック
50分で掴み取る ASP.NET Web API パターン&テクニック50分で掴み取る ASP.NET Web API パターン&テクニック
50分で掴み取る ASP.NET Web API パターン&テクニック
 
Build Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るか
Build Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るかBuild Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るか
Build Insider OFFLINE vol.01 スマートフォンサイトのこれから ~ レスポンシブ・Webデザインは救世主となり得るか
 
Beachhead implements new opcode on CLR JIT
Beachhead implements new opcode on CLR JITBeachhead implements new opcode on CLR JIT
Beachhead implements new opcode on CLR JIT
 
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive ExtensionsC#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive Extensions
 
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例までBuildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
 
スケーラビリティと耐障害性を両立するWeb アプリケーション
スケーラビリティと耐障害性を両立するWeb アプリケーションスケーラビリティと耐障害性を両立するWeb アプリケーション
スケーラビリティと耐障害性を両立するWeb アプリケーション
 
HttpClient詳解、或いは非同期の落とし穴について
HttpClient詳解、或いは非同期の落とし穴についてHttpClient詳解、或いは非同期の落とし穴について
HttpClient詳解、或いは非同期の落とし穴について
 
スマホ向けWebアプリ開発で使えるフロントエンド高速化手法
スマホ向けWebアプリ開発で使えるフロントエンド高速化手法スマホ向けWebアプリ開発で使えるフロントエンド高速化手法
スマホ向けWebアプリ開発で使えるフロントエンド高速化手法
 

Similaire à .NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)

Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義
JPCERT Coordination Center
 
OpenStack + Common Lisp
OpenStack + Common LispOpenStack + Common Lisp
OpenStack + Common Lisp
irix_jp
 
20121217 jawsug-yokohama
20121217 jawsug-yokohama20121217 jawsug-yokohama
20121217 jawsug-yokohama
Tetsuya Chiba
 
東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates
koichik
 
Ext.directことはじめ
Ext.directことはじめExt.directことはじめ
Ext.directことはじめ
Shuhei Aoyama
 
実践 Reactive Extensions
実践 Reactive Extensions実践 Reactive Extensions
実践 Reactive Extensions
Shin Ise
 
Node-v0.12の新機能について
Node-v0.12の新機能についてNode-v0.12の新機能について
Node-v0.12の新機能について
shigeki_ohtsu
 

Similaire à .NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE) (20)

Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義
 
Em synchrony について
Em synchrony についてEm synchrony について
Em synchrony について
 
OpenStack + Common Lisp
OpenStack + Common LispOpenStack + Common Lisp
OpenStack + Common Lisp
 
HTML5&API総まくり
HTML5&API総まくりHTML5&API総まくり
HTML5&API総まくり
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
 
20010901
2001090120010901
20010901
 
OSvの概要と実装
OSvの概要と実装OSvの概要と実装
OSvの概要と実装
 
Terraformで始めるInfrastructure as Code
Terraformで始めるInfrastructure as CodeTerraformで始めるInfrastructure as Code
Terraformで始めるInfrastructure as Code
 
Web API(Dynamics 365 )勉強会
Web API(Dynamics 365 )勉強会Web API(Dynamics 365 )勉強会
Web API(Dynamics 365 )勉強会
 
Lightweight-Stream-APIのあるAndroidアプリ開発
Lightweight-Stream-APIのあるAndroidアプリ開発Lightweight-Stream-APIのあるAndroidアプリ開発
Lightweight-Stream-APIのあるAndroidアプリ開発
 
20121217 jawsug-yokohama
20121217 jawsug-yokohama20121217 jawsug-yokohama
20121217 jawsug-yokohama
 
複数アプリケーションの プロセスとログを管理する ための新しいツールと手法
複数アプリケーションのプロセスとログを管理するための新しいツールと手法複数アプリケーションのプロセスとログを管理するための新しいツールと手法
複数アプリケーションの プロセスとログを管理する ための新しいツールと手法
 
Node.jsでブラウザメッセンジャー
Node.jsでブラウザメッセンジャーNode.jsでブラウザメッセンジャー
Node.jsでブラウザメッセンジャー
 
東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates
 
Cookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming ParadigmCookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming Paradigm
 
Ext.directことはじめ
Ext.directことはじめExt.directことはじめ
Ext.directことはじめ
 
SlackのIncomingWebhooksとOutgoingWebhooksを使って電子工作と連携させてみよう
SlackのIncomingWebhooksとOutgoingWebhooksを使って電子工作と連携させてみようSlackのIncomingWebhooksとOutgoingWebhooksを使って電子工作と連携させてみよう
SlackのIncomingWebhooksとOutgoingWebhooksを使って電子工作と連携させてみよう
 
実践 Reactive Extensions
実践 Reactive Extensions実践 Reactive Extensions
実践 Reactive Extensions
 
Node-v0.12の新機能について
Node-v0.12の新機能についてNode-v0.12の新機能について
Node-v0.12の新機能について
 
Couchbase MeetUP Tokyo - #11 Omoidenote
Couchbase MeetUP Tokyo - #11 OmoidenoteCouchbase MeetUP Tokyo - #11 Omoidenote
Couchbase MeetUP Tokyo - #11 Omoidenote
 

Plus de Tusyoshi Matsuzaki (6)

Apache Spark on Azure
Apache Spark on AzureApache Spark on Azure
Apache Spark on Azure
 
Minecraft による強化学習の実践 (MineRL)
Minecraft による強化学習の実践 (MineRL)Minecraft による強化学習の実践 (MineRL)
Minecraft による強化学習の実践 (MineRL)
 
Spark Analytics - スケーラブルな分散処理
Spark Analytics - スケーラブルな分散処理Spark Analytics - スケーラブルな分散処理
Spark Analytics - スケーラブルな分散処理
 
クラウドの潮流と Windows Azure の位置づけ (エフスタ Tokyo 資料)
クラウドの潮流と Windows Azure の位置づけ (エフスタ Tokyo 資料)クラウドの潮流と Windows Azure の位置づけ (エフスタ Tokyo 資料)
クラウドの潮流と Windows Azure の位置づけ (エフスタ Tokyo 資料)
 
アイデンティティ プロバイダーとの連携手法 Tsmatsuz
アイデンティティ プロバイダーとの連携手法 Tsmatsuzアイデンティティ プロバイダーとの連携手法 Tsmatsuz
アイデンティティ プロバイダーとの連携手法 Tsmatsuz
 
SharePoint 2010 を使ったクラウドアプリ開発
SharePoint 2010 を使ったクラウドアプリ開発SharePoint 2010 を使ったクラウドアプリ開発
SharePoint 2010 を使ったクラウドアプリ開発
 

Dernier

Dernier (10)

Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 

.NET Web プログラミングにおける非同期 IO のすべて (Build Insider OFFLINE)

  • 1. .NET Web プログラミングにおける 非同期 I/O のすべて 日本マイクロソフト株式会社 エバンジェリスト 松崎 剛 http://blogs.msdn.com/b/tsmatsuz
  • 2. 2 セッション ゴール • .NET Web 開発における非同期 IO の基本を学ぶ 発想の原点や歴史、基本メカニズム、用語などについて • べし・べからず、Tips、などを理解 新機能にはワケがある ! ~ スケーラブルな Web を作ろう ~
  • 3. 3 非同期のプログラミング・パターン • EAP (Event-based Asynchronous Pattern) • APM (Asynchronous Programming Model) • TAP (Task-based Asynchronous Pattern) FileStream fs; byte[] readArray = new byte[0x1000]; . . . fs.BeginRead(readArray, 0, readArray.Length, new AsyncCallback(readCallback), fs); . . . private void readCallback(IAsyncResult ar) { System.IO.FileStream fs = (System.IO.FileStream)ar.AsyncState; int fsize = fs.EndRead(ar); . . . } MyReadClass myRead = new MyReadClass(); myRead.ReadCompleted += new EventHandler<ReadCompletedEventArgs>( readCompleted); myRead.ReadAsync(); . . . private void readCompleted( object sender, ReadCompletedEventArgs e) { var res = e.Result; . . . } using (StreamReader reader = File.OpenText(filename)) { result = new char[reader.BaseStream.Length]; Task<int> t = reader.ReadAsync(result, 0, (int) reader.BaseStream.Length); }
  • 4. 4 ASP.NET における非同期の変遷 ASP.NET Web フォーム ASP.NET MVC .NET 2.0 .NET 3.5 .NET 4.5 .NET 4.0
  • 5. 5 プログラミング・パターンの相性 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { this.PreRenderComplete += new EventHandler(Page_PreRenderComplete); AddOnPreRenderCompleteAsync( new BeginEventHandler(BeginAsyncOperation), new EndEventHandler(EndAsyncOperation)); } } IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state) { _connection = new SqlConnection(connectstring); _connection.Open(); _command = new SqlCommand( "SELECT title_id, title, price FROM titles", _connection); return _command.BeginExecuteReader(cb, state); } void EndAsyncOperation(IAsyncResult ar) { _reader = _command.EndExecuteReader(ar); } protected void Page_PreRenderComplete(object sender, EventArgs e) { Output.DataSource = _reader; Output.DataBind(); } ASP.NET Async Page (APM) + DB Access (APM)
  • 6. 6 TAP + async/await (C# 5.0) public Task<ActionResult> Test1() { // Step 1 HttpClient cl = new HttpClient(); Task<HttpResponseMessage> task = cl.GetAsync(@"http://heavyweb.cloudapp.net/"); return task.ContinueWith(t => { // Step 2 ViewBag.ResultData = t.Result.ToString(); return (ActionResult)View(); }); } public async Task<ActionResult> Test1() { // Step 1 HttpClient cl = new HttpClient(); HttpResponseMessage result = await cl.GetAsync(@"http://heavyweb.cloudapp.net/"); // Step 2 ViewBag.ResultData = result.ToString(); return (ActionResult)View(); }
  • 7. 7 ASP.NET における非同期 要求 (Request)、キュー (Queue)、スレッド (Thread) Web サーバー (IIS) 要求 (Request) キュー (Queue) 処理中 … 処理中 … 処理中 … スレッド (Thread) スレッド プール
  • 14. 14 I/O Completion Port (IOCP) • Windows が提供する機構 • 1 つの IOCP は、1 つ以上のデバイス ハンドル (ファイル ハンドルな ど) と関連 • キューのメカニズムを使って、非同期 IO の完了をプログラムから検知 • スレッドの状態 (待ち状態、リリース状態、など) を監視し、スレッド の実行数を自動で制御 • IOCP でブロックされたスレッドは、いったん解放されて、LIFO の キューに入る (1 つのスレッドが継続して処理可能。可能な限り Context Switch を抑制) • Win32 API を提供 • カスタムな制御が可能 • Thread Pool API を使った I/O 処理、Timer処理 (Thread Pool Timer) で使用
  • 15. 15 15
  • 16. 16 16 public class Handler1 : IHttpHandler { public void ProcessRequest(HttpContext context) { if (context.IsWebSocketRequest) { BetsHandler1 handler = new BetsHandler1(); context.AcceptWebSocketRequest(handler.Receive); } else { context.Response.StatusCode = 400; //bad request } } . . . } public class BetsHandler1 { public WebSocket webSocket; public async Task Receive( AspNetWebSocketContext context) { webSocket = context.WebSocket; ArraySegment<byte> buf = new ArraySegment<byte>(new byte[2048]); while (true) { WebSocketReceiveResult res = await webSocket.ReceiveAsync( buf, System.Threading.CancellationToken.None); if (res.MessageType == WebSocketMessageType.Close) { // Close Message connectedHandlers.Remove(this); await webSocket.CloseOutputAsync( . . .); break; } else if (res.MessageType == WebSocketMessageType.Text) { // Text Message . . . Some kind of process } } } . . . }
  • 17. 17 17 public class Handler1 : IHttpHandler { public void ProcessRequest(HttpContext context) { if (context.IsWebSocketRequest) { BetsHandler1 handler = new BetsHandler1(); context.AcceptWebSocketRequest(handler.Receive); } else { context.Response.StatusCode = 400; //bad request } } . . . } public class BetsHandler1 { public WebSocket webSocket; public Task Receive( AspNetWebSocketContext context) { webSocket = context.WebSocket; ArraySegment<byte> buf = new ArraySegment<byte>(new byte[2048]); while (true) { WebSocketReceiveResult res = webSocket.ReceiveAsync( buf, System.Threading.CancellationToken.None); if (res.MessageType == WebSocketMessageType.Close) { // Close Message connectedHandlers.Remove(this); webSocket.CloseOutputAsync( . . .); break; } else if (res.MessageType == WebSocketMessageType.Text) { // Text Message . . . Some kind of process } } return new TaskFactory().StartNew(() => { }); } . . . }
  • 18. 18 .NET 4.5 Web の TAP 対応 (“呼ぶ” 側) • ASP.NET Web フォーム • ASP.NET Web API • WCF • WebSocket . . . protected void Page_Load(object sender, EventArgs e) { Page.RegisterAsyncTask(new PageAsyncTask(async () => { HttpClient cl = new HttpClient(); HttpResponseMessage res = await cl.GetAsync(@“http://.../"); Label1.Text = res.ToString(); })); } public class Service1 : IService1 { public async Task<string> GetDataAsync() { HttpClient cl = new HttpClient(); HttpResponseMessage res = await cl.GetAsync(@“http://.../"); return res.ToString(); } } public class ValuesController : ApiController { // GET api/values public async Task<string> Get() { HttpClient cl = new HttpClient(); HttpResponseMessage res = await cl.GetAsync(@"http://.../"); return res.ToString(); } } context.AcceptWebSocketRequest(handler.Receive); . . . public async Task Receive(AspNetWebSocketContext context) { while (true) { WebSocketReceiveResult res = await context.WebSocket.ReceiveAsync(. . .); . . . } }
  • 19. 19 IO リソースの TAP 対応 (“呼ばれる” 側) ファイル入出力 .NET 4.5 で TAP (async) のメソッド (ReadAsync, WriteAsync, CopyToAsync など) を提供 (これまでは、APM のみ) データ ベース ADO.NET .NET 4.5 で TAP (async) のメソッド (ReadAsync など) を提供 (これまでは、APM のみ) Entity Framework Entity Framework 6 で、TAP (async) をサポート (現在、ベータ版を提供) ネット ワーク REST HttpClient のメソッドは、基本的に TAP ベース WCF .NET 4.5 で自動生成される Service Refrence Proxy では、TAP (async) のメソッドを提供 クラウド Windows Azure ServiceBus 最新の WindowsAzure.ServiceBus パッケージ (NuGet) で TAP の メソッド (NamespaceManager.QueueExistsAsync など) を提供 (APM も使用可能) では、未対応のものはどうする ? (例 : WCF Data Services, Windows Azure Storage など) ますます、対応中 . . . (こうご期待!)
  • 20. 20 SynchronizationContext • スレッド間の関係を管理する抽象化されたスケジューラー・オブジェクト  ASP.NET 非同期スレッドは、Win32 メッセージ ループのように特定スレッドに紐づかない • 1 つのスレッドに対し、必ず 1 つの SynchronizationContext が存在 (ただし、単一 のSynchronizationContext は複数スレッドで共有) • 一部の実装 (override メソッド) を除き、具体的な実装は派生クラスに依存  WindowsFormsSynchronizationContext  DispatcherSynchronizationContext  AspNetSynchronizationContext  既定の SynchronizationContext • これまでの非同期処理 (EAP など) において、その動作をつかさどる • TAP では TaskScheduler を使用 (SynchronizationContext を使用する際は、 TaskScheduler.FromCurrentSynchronizationContext を明示)
  • 21. 21 SynchronizationContext • 既定の Awaiter (TaskAwaiter) は、Current の SynchronizationContext を使用 (なければ TaskScheduler も参照)  AspNetSynchronizationContext では、同期ブロックに入れるスレッドは 1 つだけ • .NET 4 以降では、Task と相性の良い新しい AspNetSynchronizationContext を使用  従来のものは LegacyAspNetSynchronizationContext に変更 この場合でも、Web.configの設定で新しいContextを 使用可能 <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext“ value="true"/> </appSettings>
  • 22. 22 混ぜるな、危険 💀 • Async (EAP, TAP, etc) と Sync の混 在プログラムは、デッドロックの原因 となる ! Task で受け取った内容を、むりやり同期 化しない (All async is beautiful !) 「扱いやすい」(理解しやすい) という理 由だけで、 Result、Wait を多用しない (初心者にありがちなミス) 現実の開発では、追跡とデバッグが非常に 困難 (例 : 単一では動作するんだけ ど ?、コンソール・アプリでは動くのに ? など)