2017-03-02 24 views
5

「CPU集約型」でないものに対してのみasyncを使用すべきであることがわかっています。ファイルの書き込み、Web呼び出しなどがあります。したがって、すべてのメソッドをTask.Runまたはそれに類するものにするのは意味がありません。非同期メソッド(Web呼び出しを行う)を非同期にラップする

しかし、メソッドがWeb呼び出しを行うが、非同期インターフェイスを提供していないことを知っているとき、私は何をすべきですか?この場合、それをラップする価値はありますか?

具体例:私は私のWEBAPIアプリケーション(サーバー)にCSOM(クライアントのSharePointオブジェクトモデル)を使用してSharePointリストを取得したいよ

これは通常、次のように行われます。

[HttpGet] 
[Route("foo/{webUrl}")] 
public int GetNumberOfLists(string webUrl) 
{ 
    using (ClientContext context = new ClientContext(webUrl)) 
    { 
     Web web = context.Web; 
     context.Load(web.Lists); 
     context.ExecuteQuery(); 

     return web.Lists.Count; 
    } 
} 

そして、私はこのような何かにそれを変更する方法について考えた:

[HttpGet] 
[Route("foo/{webUrl}")] 
public async Task<int> GetNumberOfLists(string webUrl) 
{ 
    using (ClientContext context = new ClientContext(webUrl)) 
    { 
     Web web = context.Web; 
     context.Load(web.Lists); 
     await Task.Run(() => clientContext.ExecuteQuery()); 

     return web.Lists.Count; 
    } 
} 

それは意味を成さないし、それは助けていますか?私はそれを理解しているので、私はクエリを実行するための新しいスレッド( "オーバーヘッド")を作成/必要としますが、少なくとも要求スレッドは空いている/別の要求の準備ができています。

しかし、それは価値があり、このようにするべきですか?

もしそうなら: マイクロソフトが「非同期」メソッドを提供していないのは奇妙ではないのですか、それとも気にしませんでしたか?

編集: Task.Runをコメント内の示唆通りに更新しました。

+0

'Task.Factory.StartNew'を使用せず、' Task.Run'を使用します。 * SharePoint *を呼び出す場合、コンテキストにはExecuteQueryAsyncメソッドがあり、これを使用してタスクを返すことができます。 –

+0

私のCSOMライブラリに 'ExecuteQueryAsync'がありません。 –

+0

は 'nuget経由で' Microsoft.SharePointOnline.CSOM、16.1.6216'にアップアップされましたが、そこには 'ExecuteQueryAsync'はありません。 –

答えて

3

しかし、メソッドがWeb呼び出しを行うが、非同期インターフェイスは提供されていないことを知っているときは、どうすればよいですか。

残念ながらまだ幾分一般的です。異なるライブラリがAPIを更新すると、最終的に追いつくでしょう。

この場合は、値するのですか?

はい、UIスレッドを扱っている場合。そうでなければ、いいえ。

具体例...私のWEBAPIアプリケーション(サーバー)

に続いて、いいえ、あなたはTask.Runでラップする必要はありません。私article on async ASP.NETで述べたように:

あなたはTask.Runを待っていることにより、いくつかの背景作業をキックオフすることができますが、そうするにはポイントがありません。実際には、それは実際にはASP.NETスレッドプールヒューリスティックを妨害することによってあなたのスケーラビリティを傷つけるでしょう...一般的なルールとして、ASP.NETのスレッドプールに作業をキューイングしないでください。 ASP.NETのTask.Run

ラッピング:

  • は二回(今のスレッドを服用し、後でそれを解放することによって)ASP.NETスレッドプールのヒューリスティックと干渉する。
  • オーバーヘッドを追加します(コードはスレッドを切り替える必要があります)。
  • スレッドを解放しません(この要求に使用されるスレッドの総数は、同期バージョンを呼び出すこととほとんど同じです)。

私の理解では、(それが良いでしょう)私はちょうど作成/クエリ(「オーバーヘッド」)を実行するための新しいスレッドを必要とするが、少なくとも、リクエストスレッドが別の要求のために準備/無料になります。

はい、しかし、あなたがしているのは、スレッドを飛ばしているだけなので、何のメリットもありません。クエリ結果をブロックするために使用されるスレッドは、ASP.NETが要求を処理するために使用するスレッドが1つ少ないため、別のスレッドを解放してスレッドを解放するのは良いトレードオフにはなりません。

マイクロソフトが「非同期」方式を提供していないのは奇妙ではないのですか、それとも気にしませんでしたか?

「旧式の」MS APIの中には、まだasyncバージョンを追加していないものがあります。彼らは確かにになるはずですが、開発者の時間は有限のリソースです。

+0

完璧な答え、まさに「探していた」 - ありがとう! –

0

これは私の個人的な問題です。私の場合は、上記の方法は必要ありません。 IISでAPIをホストすると、サーバーはサーバー内のスレッドプールから1つのスレッドを割り当てます。 IISには、maxConcurrentRequestsPerCPU maxConcurrentThreadsPerCPUの設定もあります。リクエストを自分で処理する代わりに、リクエストに対応するようにこれらの値を設定できます。

関連する問題