2016-04-22 53 views
1

私はAsync/Await機能の新機能で、MVCプロジェクトでそれらを使用しようとしました。私はこれらのコードを使用する最初の方法についてAsync Awaitメソッド

public async Task<CompanyBoardViewModel> GetIndexViewModel(IEnumerable<int> parameter, bool isMore = false, bool currentRole = false) 
     { 
       return new CompanyBoardViewModel 
       { 
        TopJoinAplicant = await this.TopJointApplicant(parameter, isMore), 
        TopPriorityCountry = await this.TopPriorityCountry(parameter), 
        TopPublicationCountries = await this.TopPublicationCountries(parameter), 
        TopGrantedInventors = await this.TopGrantedInventors(parameter), 
        TopIPC = await this.TopIPC(parameter), 
        TopCPC = await this.TopCPC(parameter), 
        TopCitedInventors = await this.TopCitedInventors(parameter), 
        TopCitedPatents = await this.TopCitedPatents(parameter), 
        CGAR = await this.GetCGAR(parameter), 
       }; 

} 

::私はawaitを使用してこのGetIndexViewModelで

var model = this.quantService.GetIndexViewModel(companyIds, isMore, currentrole).Result; 

だからコントローラから、私は私のモデルを初期化するために、現在のメソッドを呼び出す

private async Task<QuantTableViewModel<TopFilterViewModel>> TopJointApplicant(IEnumerable<int> ids, bool isMore = false) 
     { 

      return await Task.Run(() => new QuantTableViewModel<TopFilterViewModel> 
      { 
       Tableid = "TopJointApplicants", 
       Title = "Top Joint Applicants", 
       FirstCol = "Position", 
       SecondCol = "Joint Applicant", 
       ThirdCol = "#", 
       IsSeeMore = isMore, 
       Data = this.cache.TopJointApplicant(ids).ToList() 
      }); 
} 

この方法では、私はData = this.cache.TopJointApplicant(ids).ToList() このメソッドはプロシージャを作成し、データベースから情報を取得します(このメソッドは問題なく実行されますが、QuantTableViewModel<TopFilterViewModel>スタックを返します)。

これがなぜ起こったのか誰にでもわかっていただければ、本当にうれしいです。

+0

メソッドに適切な書式を設定できますか? –

+0

@ÖmerCinbat - 私はピアレビューを待っている編集を提出しました。 – smoksnes

+1

await + Task.Runの使用は意味がなく、実際には有害です。なぜ、いつ* asyncが良いかを調べることをお勧めします。 – usr

答えて

0

async/awaitパターンを使用する場合は、Task.Runを使用する必要はありません。

+0

私はTask.Run()を使わずに試しましたが、それがなくても受け取った時間は私が使用していない時間と同じです(ロジックは非同期ではありません)。 –

+1

@KostadinPirgov - async'は行います。 'await Task.Run()'はアンチパターンです。なぜなら、あるアクティビティーを別のスレッドに移動し、結果が利用可能になるまで現在のスレッドが処理していたものを直ちに中断するからです。 –

0

この場合、TopJointApplicantでは実際に非同期的なことは起こっていないので、パブリックメソッドは非同期で十分です。

使用する場合は、await/async-patternを完全に使用することをお勧めします。つまり、コントローラはawait/asyncも使用する必要があります。

public class YourController : Controller 
{ 
    // Note the Task<ActionResult> and async in your controller. 
    public async Task<ActionResult> YourControllerMethod() 
    { 
     var model = await this.quantService.GetIndexViewModel(companyIds, isMore, currentrole); 
     return View(model); // Or something like this. 
    } 
} 

また、命名規則を考慮してください。わかりやすくするために、非同期メソッドは接尾辞Asyncで終了する必要があります(GetIndexViewModelAsyncなど)。

編集: コメントに基づいて、待っていること/ asyncが何をするのかを明確にする必要があります。 await/async-patternを使用するため、操作は速く実行されません。むしろ逆です。 Async/awaitは、スレッド管理のオーバーヘッドを作成します。これにより、操作が遅くなる可能性があります。

代わりに、2つの主要な利点があります:非同期/を使用している場合

  1. は、あなたがスレッドをブロックしません待っています。これは、アプリケーションが他のもの(IO、DB、またはWebサービス呼び出しなど)を待機している間に、スレッドが別の要求を実行するなど、何か他の目的で使用できることを意味します。これは、DB呼び出しがより速く実行されることを意味するものではありません。しかし、それはスレッドが待っている間に何かをすることができます。 IISを使用している場合、スレッド数は限られています。したがって、高価なIOでロックするのではなく、待機中に別の要求を処理することができます。

  2. さらに多くのことを同時に行うことができます。たとえば、遅いWebサービス呼び出しを同時に実行しながら、DBにリクエストを送信することができます。これにより、同時に多くのことを行っているため、実行時間が短縮されます。ただし、制限があります。たとえば、Entity Frameworkを使用している場合、その時点で1つのスレッドだけがコンテキストにアクセスできます。しかし、DBを待っている間、あなたは何か他のことをすることができます。例えば:

    パブリッククラスMyThreadingClass {
    プライベートタスクExecuteWebServiceCallAsync(){ リターン_myService.DoSomething()を待ちます。 }

    private Task ExecuteDbQueryAsync() 
    { 
        return await _context.Customer.FirstOrDefaultAsync(); 
    } 
    
    public void DoThingsWithWaitAll() 
    { 
        var tasks = new Task[2]; 
        // Fire up first task. 
        tasks[0] = ExecuteWebServiceCallAsync(); 
        // Fire up next task. 
        tasks[1] = ExecuteDbQueryAsync(); 
        // Wait for all tasks. 
        Task.WaitAll(tasks); 
    } 
    
    public Task DoThingsWithWithAwaitAsync() 
    { 
        // Fire up first task. 
        var webServiceTask = ExecuteWebServiceCallAsync(); 
        // Fire up next task. 
        var dbTask = ExecuteDbQueryAsync(); 
        // Wait for all tasks. 
        await webServiceTask; 
        await dbTask; 
    } 
    

    }だから、

は、総括します。あなたがawait/asyncを使うべき理由は、遅い操作(DBやWebサービスなど)の実行まですべてを行うことができるときです。または、一度にいくつかのことをしたい場合。

public async Task<CompanyBoardViewModel> GetIndexViewModel(IEnumerable<int> parameter, bool isMore = false, bool currentRole = false) 
{ 
    // Let the threads start processing. 
    var topApplicantTask = this.TopJointApplicant(parameter, isMore); 
    var topPriorityCountryTask = this.TopPriorityCountry(parameter); 
    var topPublicationContriesTask = this.TopPublicationCountries(parameter); 
    var topIPCTask = this.TopIPC(parameter); 
    var topCPCTask = this.TopCPC(parameter); 
    var topCitedInventorsTask = this.TopCitedInventors(parameter); 
    var topCitetPatentsTask = this.TopCitedPatents(parameter); 
    var getCGARTask = this.GetCGAR(parameter); 

    // Await them later. 
    return new CompanyBoardViewModel 
    { 
     TopJoinAplicant = await topApplicantTask, 
     TopPriorityCountry = await topPriorityCountryTask, 
     TopPublicationCountries = await topPublicationContriesTask, 
     TopGrantedInventors = await this.TopGrantedInventors(parameter), 
     TopIPC = await topIPCTask, 
     TopCPC = await topCPCTask, 
     TopCitedInventors = await topCitedInventorsTask, 
     TopCitedPatents = await topCitetPatentsTask, 
     CGAR = await getCGARTask, 
    }; 
} 

しかし、それはアンチパターンと考えられていますので、Task.Runを回避しよう:あなたはこのような何かを行うことができ、あなたの特定のケースで

。代わりに、コントローラーから実際の操作(DB、IO、Webサービス)までawait/asyncを使用してみてください。また、上記の例では、多くのスレッディングが行われています。それは少しきれいになるはずですが、あなたは提案された解決策よりも概念実証としてそれを見ることができます。

+0

ありがとう、私は今それを試してみましょう! –

+0

私はあなたの提案を試みましたが、私が受け取った時間は私がAsync/Awaitを使用しないのと同じです。 –

+0

もう一つ:私はタスク GetIndexViewModel(IEnumerableをパラメータ、ブール値falseをisMore =、BOOL currentRole = false)を 非同期と私が編集した –

0

実際に非同期コントローラを使用できるため、非同期操作をレンダリングして同期して実行する.Resultを呼び出す必要はありません。

のようなもの:

public Task<ActionResult> Index(object parameter) 
{ 
    var model = await this.quantService.GetIndexViewModel(companyIds, isMore, currentRole); 

    return View(model); 
} 
+0

この方法で試してみましたが、うまくいきましたが、私が受け取った時間はAsync/Awaitのないメソッドを実行したときと同じです。 お寄せいただきありがとうございます。 –

2

私はあなたが私のブログ上で見ているデッドロックを説明します。要するに、don't block on async code;代わりにasync all the wayを使用してください。

しかし、あなたのアプローチには他の問題があります。他の人が指摘しているように、await Task.RunはASP.NETの反パターンです。 async ASP.NETで私の記事を読むことをお勧めします。

最後に、もう1つのヒント:間違った方向から問題に近づいています。 「非同期化」する方法を選択するのではなく、まずアプリケーションが何をしているのかを考え、最も低いレベルので非同期のI/O呼び出しをに変換します。 APIをブロックする代わりに非同期APIを使用するように変換します(つまり、Task.Runはありません)。その後、呼び出し元を非同期に変更し、呼び出し元を非同期に変更し、最終的にコントローラメソッドを非同期に変更します。