2016-08-11 11 views
-1

私は.NET Coreの初心者です。私は、次の操作を実行するコンソールアプリケーションを実装しようとしています:.NETコアによる非同期プログラミング?

  1. コンソールアプリケーションは、2つの外部APIの間の仲介として動作するはずです。例えば。 API-1およびAPI-2。

  2. データを取得するために10ミリ秒ごとにAPI-1を呼び出す必要があります。

  3. すぐにAPI-1から受信したデータを送信するためにAPI-2を呼び出します。

  4. コンソールアプリケーションはAPI-1がデータを受信するのを待つ必要がありますが、API-2からの応答を待つ必要はありません。

以下は私のコードです。期待どおりに動作しません。最初はAPI-1を予想どおり10ミリ秒で起動しますが、API-1を呼び出すのはAPI-2からの応答を受け取った後のみです。
API-2は20秒かかると仮定し、API-1も20秒後に呼び出されます。

API-2を非同期で呼び出してAPI-2レスポンスを待つ必要はありません。

namespace ConsoleApp1 
{ 
    public class Program 
    { 
     private static Timer _timer; 
     private const int TIME_INTERVAL_IN_MILLISECONDS = 10; // 10 milliseconds 
     private const int API2_DELAY = 20000; // 20 seconds 
     public static void Main(string[] args) 
     { 
      Dowork().Wait(); 
      Console.WriteLine("Press Any Key to stop"); 
      Console.ReadKey(); 
      Console.WriteLine("Done"); 
     } 

     private static async Task Dowork() 
     { 
      var data = new SomeData(); 
      _timer = new Timer(CallAPI1, data, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite); 
      await Task.Yield();    
     } 

     private static async void CallAPI1(object state) 
     {   
      var data = state as SomeData; 

      Console.WriteLine("Calling API One to get some data."); 
      data.SomeStringValue = DateTime.Now.ToString(); 

      await CallAPI2(data); 
      _timer.Change(TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite); 
     } 

     private static async Task CallAPI2(SomeData data) 
     {   
      Console.WriteLine("Calling API Two by passing some data received from API One " + data.SomeStringValue); 

      // the delay represent long running call to API 2 
      await Task.Delay(API2_DELAY); 
     } 
    } 
} 

POCOクラス

namespace ConsoleApp1 
{ 
    public class SomeData 
    { 
     public string SomeStringValue { get; set; } 
    } 
} 

またそのAPI-1およびAPI-2の点に注意してください。ASP.NETコアに1

を開発されるアップデート1
私は文の上に言い換えてみましょう。 API-1は.Netコアで開発されますが、API-2はWindowsワークフローサービスです。つまり、WFに複数の呼び出しを行うことができます。 WFは要求を保持し、一度に1つずつ処理します。

更新2
提供されたすべての回答とリンクを通過した後。私はコンソールアプリケーションの代わりに仲介者としてWindowsサービスを使用することを考えています。今すぐ.Net coreはウィンドウサービスをサポートしていませんが、nuget-packageをWindowsサービス内で.Netコアをホストできるか、または4.6.2を使用して従来のWindowsサービスを使用している可能性があります。私はWindowsサービス内で非同期実装を行うこともできると思います。

+0

C#でコンソールアプリケーションで[async]が重複している可能性があります(http://stackoverflow.com/questions/17630506/async-at-console-app-in-c) –

+0

@ LP13なぜAPI2が遅いのですか?何してるの?遅いサービスへの複数の呼び出しを行うことは、おそらくそれを飽和させるでしょう。スレッド飢餓、I/O飽和などの問題が発生する可能性があります。より具体的にすることができます –

+0

[async void]を避ける(https://msdn.microsoft.com/en-us/magazine/jj991977.aspx ) –

答えて

0

API2

private static async void CallAPI1(object state) 
    { 
     var data = state as SomeData; 

     Console.WriteLine("Calling API One to get some data."); 
     data.SomeStringValue = DateTime.Now.ToString(); 
     //Before this will cause the program to wait 
     await CallAPI2(data); 
     // Now it will call and forget 
     CallAPI2(data); 
     _timer.Change(TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite); 
    } 

編集呼び出すときのawaitを削除します。

ダビデが指摘するように、もちろん、この問題を解決するための多くの方法があるが。これはあなたの問題を解決する正しい方法ではありません。

もう1つの方法は石英を使用しています。繰り返しジョブとしてネット

  1. スケジュールAPI1
  2. API1が行われると、API2が失敗したとき、あなたが仕事を繰り返す/再生することができますこの方法でスタンドアロンジョブとして

をAPI2を実行するために、別のジョブをスケジュールします。

+1

OPが明示的にこれを求めているという理由だけで正しいとは限りません。あなたが何か他のものを考慮する必要があると思ったら、OPに言い聞かせてください。 –

2

この状況では、私は多少異なることがあります。タイマーを使用するのではなく、Task.Delayを使用します。もっと多くのデータを投げようとする前に、API2が完了するまで待つのが最も確実です。また、asyncのメソッドがTaskまたはTask<T>であることを確認します。CallAPI1コールがそうでないことに気づくでしょう。それはタイマーコールバックですが、それは別の問題です。

は、次のことを考えてみましょう:

async Task IntermediateAsync() 
{ 
    Console.WriteLine("Press ESC to exit..."); 

    while (Console.ReadKey(true).Key != ConsoleKey.Escape) 
    { 
     var result = await _apiServiceOne.GetAsync(); 
     await _apiServiceTwo.PostAsync(result); 

     // Wait ten milliseconds after each successful mediation phase 
     await Task.Delay(10); 
    } 
} 

これは、次のように動作します:

  1. 印刷
  2. スタートループ
  3. を終了するにはどのようにユーザに指示行をした結果を取得します。 API1
  4. 結果をAPI2に渡す
  5. [ステップ2]

最後に、これは関係なく、あなたの.NET Coreを使用しているか否かの同じ提案である10ミリ秒

  • を待ちます。すべてのAPIのやりとりは、同じガイドラインに従う必要があります。

    ノート

    単に失敗のあなたのコードを上に設定された第2のAPI呼び出しでファイア・アンド・フォーゲットを使用しました。 APIコールであるため、I/Oバインド操作では待ち時間が増える可能性があります。また、10ミリ秒のタイトなループでは、そのエンドポイントでの可用性があふれてしまうと想定する必要があります。単にそれが終了するのを待つだけでは、あなたはおそらくどのような理由がありますか?

  • +0

    ありがとうございます。パフォーマンスが、私がWF(API-2)を待つことを望まない理由です。 WFにできるだけ多くのリクエストを提出したいと思います。ここで私が使った10ミリ秒は、例えば実際には10分後に毎回API-1をポーリングすることになります。 update1 – LP13

    +0

    @ LP13を参照してください、私の答えは依然として望ましい機能です。特に実際の状況では、それが完了するまで待つことを望むでしょう。あなたがバックグラウンドワーカーであるため、この時点ではパフォーマンスは問題にはならず、ループ間で10分待っています。 –

    +0

    仲介業者は、ワークフローが完了するのを待つことはできません。(申し訳ありませんが、API-2と呼ばれていました)これらは長時間実行されているプロセスなので、Windows Workflowを使用しています。 – LP13

    関連する問題