2012-09-01 5 views
5

ここに状況があります。JSONをyield returnを使用して「生きて」返すことができますか?

私は何をして働いています: - ASP.NET MVC 4のWeb API - アプリケーション をホストするIIS 7.0を - C#

私は、イントラネット上のリモートマシンからパフォーマンスデータを取得したWeb APIを持っているし、テストしていURL呼び出しを介してAPIを呼び出すとJSONが返されます。ただし、JSONを返す前に実行を完了する必要があります。たとえば、パフォーマンス監視を10秒間戻した場合、すべてのデータ値を表示する前に10秒待たなければなりません。

パフォーマンスカウンタを毎秒読み取ってJSONで表示すると、すべてを取得するのを待つのではなく、一度にすべてを一覧表示するのではなく、値を返すようにしたい。これを達成するためにYIELDキーワードを使用しようとしていますが、まだ動作していません。メソッドが完全に終了するまでJSONはブラウザに表示されません。 LogDBRepository.csから

public IEnumerable<DataValueInfo> LogTimedPerfDataLive(string macName, string categoryName, string counterName, 
              string instanceName, string logName, long? seconds) 
    { 
     iModsDBRepository modsDB = new iModsDBRepository(); 
     List<MachineInfo> theMac = modsDB.GetMachineByName(macName); 

     if (theMac.Count == 0) 
      yield break; 

     else if (instanceName == null) 
     { 
      if (!PerformanceCounterCategory.Exists(categoryName, macName) || 
       !PerformanceCounterCategory.CounterExists(counterName, categoryName, macName)) 
      { 
       yield break; 
      } 
     } 
     else if (instanceName != null) 
     { 
      if (!PerformanceCounterCategory.Exists(categoryName, macName) || 
       !PerformanceCounterCategory.CounterExists(counterName, categoryName, macName) || 
       !PerformanceCounterCategory.InstanceExists(instanceName, categoryName, macName)) 
      { 
       yield break; 
      } 
     } 
     else if (logName == null) 
     { 
      yield break; 
     } 

     // Check if entered log name is a duplicate for the authenticated user 
     List<LogInfo> checkDuplicateLog = this.GetSingleLog(logName); 
     if (checkDuplicateLog.Count > 0) 
     { 
      yield break; 
     } 

     PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName, theMac[0].MachineName); 
     if (category.CategoryName == null || category.MachineName == null) 
     { 
      yield break; 
     } 

     List<LogInfo> logIt = new List<LogInfo>(); 
     if (category.CategoryType != PerformanceCounterCategoryType.SingleInstance) 
     { 
      List<InstanceInfo> instances = modsDB.GetInstancesFromCatMacName(theMac[0].MachineName, category.CategoryName); 

      foreach (InstanceInfo inst in instances) 
      { 
       if (!category.InstanceExists(inst.InstanceName)) 
       { 
        continue; 
       } 
       else if (inst.InstanceName.Equals(instanceName, StringComparison.OrdinalIgnoreCase)) 
       { 
        PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName, 
                     inst.InstanceName, theMac[0].MachineName); 

        //CounterSample data = perfCounter.NextSample(); 
        //double value = CounterSample.Calculate(data, perfCounter.NextSample()); 
        string data = ""; 
        List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name); 

        string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt"); 

        List<string> dataValues = new List<string>(); 
        for (int i = 0; i < seconds; i++) 
        { 
         data = "Value " + i + ": " + perfCounter.NextValue().ToString(); 
         DataValueInfo datItUp = new DataValueInfo 
         { 
          Value = data 
         }; 
         yield return datItUp; 
         dataValues.Add(data); 
         Thread.Sleep(1000); 
        } 
        string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt"); 

        Log log = new Log 
        { 
         LogName = logName, 
         CounterName = perfCounter.CounterName, 
         InstanceName = perfCounter.InstanceName, 
         CategoryName = perfCounter.CategoryName, 
         MachineName = perfCounter.MachineName, 
         TimeStarted = timeStarted, 
         TimeFinished = timeFinished, 
         PerformanceData = string.Join(",", dataValues), 
         UserID = currUser[0].UserID 
        }; 
        this.CreateLog(log); 
        break; 
       } 
      } 
     } 
     else 
     { 
      PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName, 
                     "", theMac[0].MachineName); 


      string data = ""; 
      List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name); 

      string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt"); 

      List<string> dataValues = new List<string>(); 

      for (int i = 0; i < seconds; i++) 
      { 
       data = "Value " + i + ": " + perfCounter.NextValue().ToString(); 
       DataValueInfo datItUp = new DataValueInfo 
       { 
        Value = data 
       }; 
       yield return datItUp; 
       dataValues.Add(data); 
       Thread.Sleep(1000); 
      } 
      string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt"); 

      Log log = new Log 
      { 
       LogName = logName, 
       CounterName = perfCounter.CounterName, 
       InstanceName = perfCounter.InstanceName, 
       CategoryName = perfCounter.CategoryName, 
       MachineName = perfCounter.MachineName, 
       TimeStarted = timeStarted, 
       TimeFinished = timeFinished, 
       PerformanceData = string.Join(",", dataValues), 
       UserID = currUser[0].UserID 
      }; 
      this.CreateLog(log); 
     } 

    } 

LogController.csから:ここで

は、リポジトリ方式のためと調整コントローラのアクションのためのコードがある

[AcceptVerbs("GET", "POST")] 
    public IEnumerable<DataValueInfo> Log_Perf_Data(string machine_name, string category_name, string counter_name, string instance_name, 
            string log_name, long? seconds, string live, string enforceQuery) 
    { 
     LogController.CheckUser(); 

     // POST api/log/post_data?machine_name=&category_name=&counter_name=&instance_name=&log_name=&seconds= 
     if (machine_name != null && category_name != null && counter_name != null && log_name != null && seconds.HasValue && enforceQuery == null) 
     { 
      List<DataValueInfo> dataVal = logDB.LogTimedPerfDataLive(machine_name, category_name, counter_name, instance_name, 
            log_name, seconds).ToList(); 
      logDB.SaveChanges(); 
      foreach (var val in dataVal) 
       yield return val; 
     } 

     yield break; 
    } 

をいただき、ありがとうございますあなたの時間と配慮。

+1

'yield'キーワードで作成された反復子関数は、要求に応じて次の項目を引き出すように設計されています。彼らは彗星のようなものではなく、サーバーからクライアントにデータをプッシュします。おそらく、彗星の技術について少し研究する必要があります。 –

+0

クライアントコードも完全な応答を待つので、ソリューションが簡単だとは思いません。 私は@KendallFreyに同意します。これを望むなら、あなたはcometを使う必要があります。 –

+0

ありがとうございます。私は彗星のエンコーディングをコントローラーに入れますか? – praetor

答えて

1

返答がフラッシュされたときに返されるメモリオブジェクトを作成するだけで、結果がメモリオブジェクトになります。

これを行う最も簡単な方法は、同期された(静的な)変数でサーバー上にjsonを維持することです.Jsonを作成してパフォーマンスデータを表示するよう要求すると、バックグラウンドワーカー(web backgrounder nuget)データをjsonオブジェクトに埋め込み、実行フラグを設定してjsonオブジェクトを返します(開始時にはおそらく空です)。

ブラウザからsetIntervalを使用すると、毎秒serverを呼び出すことでこのデータを更新するので、データが増えてくるたびに応答が得られます。バックグラウンドスレッドが完了すると、runningフラグをfalseに設定し、次の呼び出しでjsonの情報を返すので、クライアントからのリフレッシュを停止できます。

これはではない最も良い方法ですが、実装が最も簡単です。

関連する問題