LoginSignup
0
0

More than 1 year has passed since last update.

Couchbase .Net SDK解説:非同期プログラミング

Posted at

概要

Couchbase .NET SDKは、System.Threading.Tasks名前空間のクラスを用いた「タスクベースの非同期パターン(TAP)」を使用して、るCouchbaseServerに対する非同期操作を実現します。同期操作のための固有のAPIはない代わりに、Task.Resultメソッドを使用して、すべてのタスクをブロッキング方式で同期的に実行できます。

.Netにおける非同期プログラミング、特に「タスクベースの非同期パターン(TAP)」に関する詳しい情報は、こちらのMicrosoftのドキュメントをご確認ください。

実装例による解説

Couchbase Serverへの接続

後述の全ての処理は、Clusterオブジェクトで接続を開始し、バケットとコレクションをオープンするところから始まります。

var cluster = new Cluster("couchbase://localhost", new ClusterOptions()
                 .WithConnectionString("couchbase://localhost")
                 .WithCredentials(username: "user", password: "password")
                 .WithBuckets("travel-sample")
            );

var bucket = await cluster.BucketAsync("default");
var collection = bucket.DefaultCollection();

awaitを使用した非同期プログラミング

awaitの利用は、非同期操作を行うための最も基本的な方法です。

var upsertResult = await collection.UpsertAsync("doc1",new {Name = "Ted", Age = 80});
using (var getResult = await collection.GetAsync("doc1"))
{
     var person = getResult.ContentAs<dynamic>();
}

ここでは、例外処理は考慮していないことにご注意ください。

GetAsyncメソッドは、GetResultを返します。そのGetResultContentAsメソッドを使用して、戻り値を読み取ります。

Task.Resultを使用した同期プログラミング

上記で利用した同じメソッド(UpsertAsync, GetAsync)を同期的に呼び出すこともできます。その場合、次のように、Resultプロパティを使用します。

var upsertResult = collection.UpsertAsync("doc1",new {Name = "Ted", Age = 80}).Result;
using (var getResult = collection.GetAsync("doc1").Result)
{
     var person = getResult.ContentAs<dynamic>();
}

上記の同期処理と同様のことを行う別の方法は、Task.GetAwaiter().GetResult()のようにAwaiterを明示的に呼び出すことです。

var upsertResult = collection.UpsertAsync("doc1",new {Name = "Ted", Age = 80}).GetAwaiter().GetResult();
using (var getResult = collection.GetAsync("doc1").GetAwaiter().GetResult())
{
     var person = getResult.ContentAs<dynamic>();
}

Task.WhenAllを使用して多数のタスクを同時に実行する

特定の状況では、多数のタスクの(実行順序のない)組み合わせを同時に実行したい場合があります。このようなバッチ処理を行うためには、Task.WhenAllを使用します。

var tasks = new List<Task<IGetResult>>
{
    collection.GetAsync("doc1"),
    collection.GetAsync("doc2"),
    collection.GetAsync("doc3"),
    collection.GetAsync("doc4")
};

var results = await Task.WhenAll(tasks);

foreach (var getResult in results)
{
    var doc = getResult.ContentAs<dynamic>();
    //戻り値のドキュメントに対する処理
}

この例では、4つのドキュメントを非同期にフェッチし、全ての結果が返されるまで状態を一時停止します。次に、結果のリストをループして各ドキュメントを同期的に処理しています。

上述したように、非同期処理は、実行順序に関係のないタスクの組み合わせの実行という意味で、本質的にバッチ操作です。

下では、上とは少し異なる方法による実装例にコメントを附しています。

// Taskリストの初期化
var tasks = new List<Task>();

// 同期的にタスクを作成し、リストに格納(これらのタスクはまだスケジュールされていません)
for (var i = 0; i <100; i++)
{
    var task = collection.GetAsync($"mykey-{i}");
    tasks.Add(task);
}

// リスト中の全てのタスクの完了を待つ
await Task.WhenAll(tasks);

// リストから順次、結果を受け取る
foreach (var task in tasks)
{
    var result = tasks.Result;
}

参考情報

Couchbase公式ドキュメント .NET SDK / Advanced Data Operations / Async & React APIs

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0