2017-05-18 3 views
1

APIが寿命の兆候を示した後に、データをAPIに送信するためにキューを作成しようとしています。次のコードでc#System.InvalidOperationExceptionキューを作成しようとするとき

のSystem.InvalidOperationException:

private void sendHandler() 
    { 
     while (true) 
     { 
      if (!sendQueueActive && sendQueue.Count >= 1) 
      { 
       sendQueueActive = true; 
       foreach (relays relays in sendQueue) 
       {       
        dynamic result = IoLogikApiConnector.put("io/relay", relays); 
        int code = result.error.code; 
        if (code != 0) 
        { 
         _log.logErrorToApi("Cannot write to IoLogik", "Error code:" + result, _deviceID); 
         _device.logErrorToApi(); 
         sendQueue.Remove(relays); 
        } 
        else 
        { 

         _device.logConnectedToApi(); 
         sendQueue.Remove(relays); 
        } 
        sendQueueActive = false; 

       } 
      } 
      else 
      { 
       Thread.Sleep(20); 
      } 
     } 
    } 
+2

まあ、* *以下のコードでからカット&ペーストの例ですか..?例外メッセージとは何ですか? –

+0

foreachループ内のこのプログラムは、このコードがQueueList内の「リレー」を削除したいときにListにデータを書き込みます。 –

+0

'sendQueue'の型は何ですか? 'Queue 'には 'Remove'メソッドはありません。 – Lee

答えて

2

あなたはforeachのを使用しながら、キューから項目を削除します。決して良いことではありません。

using System.Linq; 
using System.Collections.Generic; 
using System.Collections; 

private void sendHandler() 
{ 
    while (true) 
    { 
     if (!sendQueueActive && sendQueue.Count >= 1) 
     { 
      sendQueueActive = true; 

      // MAKE A COPY FIRST 
      var sendQueueCopy = sendQueue.ToList(); 

      foreach (relays relays in sendQueueCopy) 
      {       
       dynamic result = IoLogikApiConnector.put("io/relay", relays); 
       int code = result.error.code; 
       if (code != 0) 
       { 
        _log.logErrorToApi("Cannot write to IoLogik", "Error code:" + result, _deviceID); 
        _device.logErrorToApi(); 
        sendQueue.Remove(relays); 
       } 
       else 
       { 

        _device.logConnectedToApi(); 
        sendQueue.Remove(relays); 
       } 
       sendQueueActive = false; 

      } 
     } 
     else 
     { 
      Thread.Sleep(20); 
     } 
    } 
} 

が、より良いスレッドセーフなキューを使用を書くことが

良いです。

https://msdn.microsoft.com/en-us/library/dd997371(v=vs.110).aspx

ここで上記のリンク

 // A bounded collection. It can hold no more 
     // than 100 items at once. 
     BlockingCollection<Data> dataItems = new BlockingCollection<Data>(100); 


     // A simple blocking consumer with no cancellation. 
     Task.Run(() => 
     { 
      while (!dataItems.IsCompleted) 
      { 

       Data data = null; 
       // Blocks if number.Count == 0 
       // IOE means that Take() was called on a completed collection. 
       // Some other thread can call CompleteAdding after we pass the 
       // IsCompleted check but before we call Take. 
       // In this example, we can simply catch the exception since the 
       // loop will break on the next iteration. 
       try 
       { 
        data = dataItems.Take(); 
       } 
       catch (InvalidOperationException) { } 

       if (data != null) 
       { 
        Process(data); 
       } 
      } 
      Console.WriteLine("\r\nNo more items to take."); 
     }); 

     // A simple blocking producer with no cancellation. 
     Task.Run(() => 
     { 
      while (moreItemsToAdd) 
      { 
       Data data = GetData(); 
       // Blocks if numbers.Count == dataItems.BoundedCapacity 
       dataItems.Add(data); 
      } 
      // Let consumer know we are done. 
      dataItems.CompleteAdding(); 
     }); 
+0

ありがとうございますが、sendQueue.ToList();利用できません? –

+0

sendQueueの型は正確に何ですか? 'IEnumerable ' – bradgonesurfing

+0

オブジェクトを含むリストを実装すると仮定します。 –

関連する問題