c#排队时System.InvalidOperation异常
我试图构建一个队列,在API给出生命迹象后将数据发送到API 以下代码中的System.InvalidOperationException:c#排队时System.InvalidOperation异常,c#,C#,我试图构建一个队列,在API给出生命迹象后将数据发送到API 以下代码中的System.InvalidOperationException: private void sendHandler() { while (true) { if (!sendQueueActive && sendQueue.Count >= 1) { sendQueueActive
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);
}
}
}
您正在使用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);
}
}
}
但最好使用线程安全队列
下面是上面链接中的剪切粘贴示例
// 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();
});
//一个有界集合。它再也装不下了
//一次超过100件物品。
BlockingCollection数据项=新BlockingCollection(100);
//一个没有取消的简单阻塞消费者。
Task.Run(()=>
{
而(!dataItems.IsCompleted)
{
数据=空;
//如果number.Count==0,则阻塞
//IOE表示对已完成的集合调用了Take()。
//其他线程可以在我们通过后调用CompleteAdding
//我已完成支票,但在我们打电话之前。
//在本例中,我们可以简单地捕获异常,因为
//循环将在下一次迭代中中断。
尝试
{
data=dataItems.Take();
}
捕获(无效操作异常){}
如果(数据!=null)
{
过程(数据);
}
}
Console.WriteLine(“\r\n没有更多的项目要获取。”);
});
//一个简单的阻塞生产者没有取消。
Task.Run(()=>
{
while(moreItemsToAdd)
{
Data=GetData();
//如果numbers.Count==dataItems.BoundedCapacity,则阻止
添加(数据);
}
//让消费者知道我们已经完成了。
dataItems.CompleteAdding();
});
那么,以下代码中的哪一个。。?异常消息是什么?在foreach循环中,程序正在向列表写入数据,而此代码希望删除队列列表中的“中继”。sendQueue的类型是什么?Queue
上没有Remove
方法。它是一个自定义对象的列表。如果是由于在foreach循环中删除集合中的项(可能是这样),则异常消息会告诉您确切的问题。始终检查该选项。谢谢,但sendQueue.ToList()不可用;不可用?sendQueue的具体类型是什么??我假设它应该实现IEnumerable
它是一个包含object的列表。您可以显示声明吗。它来自哪个库/命名空间。使用System.Collections.Generic;私有列表sendQueue=新列表()代码>