I was asking for any ConcurentSet/ConcurentQueue implementation here how to create no-duplicates ConcurrentQueue? but noone suggested anything.
So I've decided to wrote it myself, modified MSDN example slightly.
I've created ConcurentSet class. I insert the same element twice, and expect it to be inserted only once, because Set is used inside:
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
However according to output elements inserted twice:
Add:0 Count=0
Add:0 Count=1
Add:1 Count=2
Add:1 Count=3
Add:2 Count=4
Take:0
Add:2 Count=5
Add:3 Count=6
Add:3 Count=7
Add:4 Count=7
Add:4 Count=8
Take:3
Add:5 Count=9
Add:5 Count=10
Add:6 Count=11
Add:6 Count=12
The question is - why my ConcurentSet implementation doesn't work as expected?
I expect such output:
Add:0 Count=0
Add:0 Count=0
Add:1 Count=1
Add:1 Count=1
Add:2 Count=2
Take:0
Add:2 Count=1
Add:3 Count=2
Add:3 Count=2
Add:4 Count=3
Add:4 Count=3
Take:3
Add:5 Count=3
Add:5 Count=3
.....
Full listing below:
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace BCBlockingAccess
{
using System;
using System.Collections.Concurrent;
public class ConcurentSet
: IProducerConsumerCollection<int>
{
private readonly object m_lockObject = new object();
private readonly HashSet<int> m_set = new HashSet<int>();
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public int Count { get { return m_set.Count; } }
public object SyncRoot { get { return m_lockObject; } }
public bool IsSynchronized { get { return true; } }
public void CopyTo(int[] array, int index)
{
throw new NotImplementedException();
}
public bool TryAdd(int item)
{
lock (m_lockObject)
{
m_set.Add(item);
}
return true;
}
public bool TryTake(out int item)
{
lock (m_lockObject)
{
foreach (var i in m_set)
{
if (m_set.Remove(i))
{
item = i;
return true;
}
}
item = -1;
return false;
}
}
public int[] ToArray()
{
throw new NotImplementedException();
}
public IEnumerator<int> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
// Increase or decrease this value as desired.
int itemsToAdd = 50;
// Preserve all the display output for Adds and Takes
Console.SetBufferSize(80, (itemsToAdd * 5) + 3);
// A bounded collection. Increase, decrease, or remove the
// maximum capacity argument to see how it impacts behavior.
BlockingCollection<int> numbers = new BlockingCollection<int>(new ConcurentSet());
// A simple blocking consumer with no cancellation.
Task.Factory.StartNew(() =>
{
int i = -1;
while (!numbers.IsCompleted)
{
try
{
i = numbers.Take();
}
catch (InvalidOperationException)
{
Console.WriteLine("Adding was compeleted!");
break;
}
Console.WriteLine("Take:{0} ", i);
// Simulate a slow consumer. This will cause
// collection to fill up fast and thus Adds wil block.
Thread.SpinWait(100000);
}
Console.WriteLine("\r\nNo more items to take. Press the Enter key to exit.");
});
// A simple blocking producer with no cancellation.
Task.Factory.StartNew(() =>
{
for (int i = 0; i < itemsToAdd; i++)
{
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
}
// See documentation for this method.
numbers.CompleteAdding();
});
// Keep the console display open in debug mode.
Console.ReadLine();
}
}
}
BlockingCollection maintains its own count and doesn't use count of underlying ConcurrentSet of yours therefore even if duplicates are ignored, the count increases.
You might want to write your own wrapper around this collection which returns count from the concurrentset and relays every other method property to the blocking collection.
Related
Here is the piece of code which represents so-called wrapper class PriorityQueue which contains three ordinary queues of different priority (High, Medium and Low) and tied with Enumeration Priority to which class Package () is connected via it's read-only property by the name Priority. And the Priority is being assigned via CreatePackage() method of PackageFactory class which creates objects (instances) of class Package (Package class have a constructor which requires to point it's _priority member in parentheses) using Random class and cast from int to Priority. This is the general background. Code is following below:
namespace PriorityQueue
{
enum Priority
{
High,
Medium,
Low
}
interface IPrioritizable
{
Priority Priority { get; }
}
class PriorityQueue<T> where T:IPrioritizable
{
private Queue<T> _queueHigh = new Queue<T>();
private Queue<T> _queueMedium = new Queue<T>();
private Queue<T> _queueLow = new Queue<T>();
public void Enqueue(T item)
{
switch (item.Priority)
{
case PriorityQueue.Priority.High:
_queueHigh.Enqueue(item);
break;
case PriorityQueue.Priority.Medium:
_queueMedium.Enqueue(item);
break;
case PriorityQueue.Priority.Low:
_queueLow.Enqueue(item);
break;
default:
throw new ArgumentOutOfRangeException(item.Priority.ToString(), "Bad priority in Priority queue. ");
}
}
public T Dequeue()
{
Queue<T> queueTop = TopQueue();
if (queueTop != null & queueTop.Count > 0)
{
return queueTop.Dequeue();
}
return default(T);
}
private Queue<T> TopQueue()
{
if (_queueHigh != null & _queueHigh.Count > 0) return _queueHigh;
if (_queueMedium != null & _queueMedium.Count > 0) return _queueMedium;
if (_queueLow != null & _queueLow.Count > 0) return _queueLow;
return _queueLow;
}
public int Count ()
{
return _queueHigh.Count + _queueMedium.Count + _queueLow.Count;
}
public bool IsEmpty()
{
return (_queueHigh.Count == 0) & (_queueMedium.Count == 0) & (_queueLow.Count == 0);
}
}
class Package:IPrioritizable
{
private Priority _priority;
public Package(Priority priority)
{
_priority = priority;
}
public Priority Priority => _priority;
}
class PackageFactory
{
Random _randgen = new Random();
public Package CreatePackage()
{
int numOfPriority = _randgen.Next(3);
return new Package((Priority)numOfPriority);
}
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Creating PriorityQueue...");
PriorityQueue<Package> pq = new PriorityQueue<Package>();
Package pack;
PackageFactory fact = new PackageFactory();
Random rnd = new Random();
Console.WriteLine("\nNow we are going to create random number of 0-20 range as a number of packets to be created. ");
int numsToCreate = rnd.Next(20);
Console.WriteLine("\nAnd now we are creating {0} packages: ", numsToCreate);
for (int i = 0; i < numsToCreate; i++)
{
Console.Write("\tPackage {0} ", i);
pack = fact.CreatePackage();
Console.WriteLine("priority is: {0} ", pack.Priority);
pq.Enqueue(pack);
}
int total = pq.Count();
Console.WriteLine("\nTotal number of packages received is: {0}", total);
Console.WriteLine("\nNow we are going to create random number of 0-20 range as a number of packets to be removed. ");
int numsToRemove = rnd.Next(20);
Console.WriteLine("\nAnd now we are removing up to {0} packages: ", numsToRemove);
for (int i = 0; i < numsToRemove; i++)
{
pack = pq.Dequeue();
if(pack != null)
{
Console.WriteLine("Removed (shipped) package with priority: {0} ", pack.Priority);
}
}
Console.WriteLine("\nNumber of packages removed (shipped) is: {0}", total - pq.Count());
Console.WriteLine("\nPress any key to terminate program...");
Console.ReadKey();
}
}
}
Also there are customised Enqueue() and Dequeue() methods for PriorityQueue class. Actually what I don't understand is the Main() part of the program where we are using customised Dequeue() method to remove instances of Package class. How does the program learns of removed package via Priority property after customised Dequeue() method being used? Object was removed and how it can learn it Priority? Does it have to do something with reference types? Here is the part which I question:
for (int i = 0; i < numsToRemove; i++)
{
pack = pq.Dequeue();
if(pack != null)
{
Console.WriteLine("Removed (shipped) package with priority: {0} ", pack.Priority);
}
}
I am trying to make a todo application in c#. What I want to do is to be able to mark a Task as done somehow. Does anyone know how to do this?
This is my program class where i print out the list in a foreach:
using System;
namespace ToDo
{
class Program
{
static void Main(string[] args)
{
bool isRunning = true;
var collection = new TodoCollection();
while (isRunning)
{
var menu = new menu();
menu.Title();
menu.Options();
int choices;
choices = Convert.ToInt32(Console.ReadLine());
switch (choices)
{
case 1:
var inputNewTask = Console.ReadLine();
var task = new Task(inputNewTask, false);
collection.Add(task);
Console.Clear();
Console.ReadLine();
break;
case 2:
int counter = 0;
if (collection != null)
{
Console.WriteLine("Dagens uppgifter listas här nedanför");
foreach (Task newTask in collection)
{
counter++;
Console.WriteLine($"({counter}) [] {newTask.ShowTask()}");
}
int userInput = Convert.ToInt32(Console.ReadLine());
Task selectedTask = collection.GetTask(userInput);
selectedTask.Done();
}
break;
}
}
}
}
}
In my foreach loop there's a empty scuare brackets i wanna change to an "X" with user input.
Here is my class for my Todo collection containing my list:
using System.Collections;
using System.Collections.Generic;
namespace ToDo
{
public class TodoCollection : IEnumerable<Task>
{
//Deklarerar mina fält
List<Task> _CurrentTasks = new List<Task>();
//Funktion som låter användaren läga till nya tasks i listan
public void Add(Task NewTask)
{
_CurrentTasks.Add(NewTask);
}
public Task GetTask(int userInput)
{
return _CurrentTasks[userInput];
}
//Låter mig iterera igenomm listan _CurrentTasks
public IEnumerator<Task> GetEnumerator()
{
return ((IEnumerable<Task>)_CurrentTasks).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_CurrentTasks).GetEnumerator();
}
}
}
``´
And I also have a class for my Tasks here:
namespace ToDo
{
public class Task
{
string _Name;
bool isDone = false;
public Task(string name, bool done)
{
this._Name = name;
this.isDone = done;
}
public string ShowTask()
{
return this._Name;
}
public bool Done()
{
isDone = true;
return isDone;
}
}
}
I assume that option 2 is "mark task as done", and you print out the list of tasks, then ask the user which one to mark as done:
Console.WriteLine("Dagens uppgifter listas här nedanför");
foreach (Task newTask in collection)
{
counter++;
Console.WriteLine($"({counter}) [] {newTask.ShowTask()}");
}
int userInput = Convert.ToInt32(Console.ReadLine());
Task selectedTask = collection.GetTask(userInput);
selectedTask.Done();
Because "print the list of tasks" sounds like somethign we would want to do often, we should make it a method:
static void PrintListOfTasks(ToDoCollection what){
foreach (Task newTask in what)
{
counter++;
Console.WriteLine($"({counter}) [] {newTask.ShowTask()}");
}
}
Let's also make it show an X if the task is done and a space if it isn't:
Console.WriteLine($"({counter}) [{newTask.IsDone() ? 'X' : ' '}] {newTask.ShowTask()}");
But now there's another problem: Task doesn't have a way to tell if it's done or not, it only has a Done() method that marks it as done. You haven't used c# properties anywhere so I haven't used one in my recommendation here; instead we could make a method that just reports back the current Task state. CopyPaste the Done() method and change the pair so the existing single "mark it as done and report back the current state" (which is a little bit nonsensical, because we know what the state of a boolean must be if we just marked it as true) is instead two different methods, one that sets the value, and one that gets the value:
public void MarkAsDone()
{
isDone = true;
}
public bool IsDone()
{
return isDone;
}
Now you can use the get verison in your WriteLine display, and you can use your set version in the "mark task as done" menu option
Finally, you can adjust your loop that does option 2, so it's a logic of:
PrintList (pass in the collection)
Ask user which to mark as done
Mark it as done
Print List again to confirm to the user it was done
I have an Octet class that is suppose to "package" eight samples and then send them forward. It has methods to add a new sample, check if it is already full, and to extract a Frame datastructure built from the eight values from the Octet.
The Octet class throws two kinds of exceptions: "cannot extract because not yet full" and "cannot add sample because already full". For that, the client code should check if full before calling Add, and extract as soon as is full, as well as to reset it (quite a lame class contract, to be honest).
The problem is: I am getting the two kinds of errors, even though the client class - the only one using Octet - seems to be performing the checks correctly before the operations that throw, but even though the error conditions are being hit. To make matters worse, when I check the values when debugger breaks, they are correct, that is, the exceptions should not be throwing!
public class Client
{
private Octet _octet = new Octet();
void ProcessNewSamples(IEnumerable<int> newSamples)
{
foreach (int sample in newSamples)
{
if (!_octet.IsFull)
{
_octet.Add(sample);
}
if (_octet.IsFull)
{
var frame = _octet.ExtractFrame();
this.SendElsewhere(frame);
_octet.Reset();
}
}
}
}
public class Octet
{
const int ARRAY_SIZE = 8;
int[] _samples = new int[ARRAY_SIZE];
int _index = 0;
public bool IsFull { get { return _index >= 8; } }
public void Add(int sample)
{
if (IsFull)
{
throw new InvalidOperationException();
}
else
_samples[_index++] = sample;
}
public Frame<int> ExtractFrame()
{
if (!IsFull)
throw new InvalidOperationException();
else
return new Frame<int>(_samples);
}
public void Reset()
{
_samples = new int[ARRAY_SIZE];
_index = 0;
}
}
As mentioned in the comment, you should place a lock if your function is accessed in parallel.
If SendElsewhere is fast, I simply would place the lock around the function:
void ProcessNewSamples(IEnumerable<int> newSamples)
{
lock (this)
{
foreach (int sample in newSamples)
{
if (!_octet.IsFull)
{
_octet.Add(sample);
}
if (_octet.IsFull)
{
var frame = _octet.ExtractFrame();
this.SendElsewhere(frame);
_octet.Reset();
}
}
}
}
Otherwise I would collect all frames and send them afterwards:
void ProcessNewSamples(IEnumerable<int> newSamples)
{
var frames = new List<Frame>();
lock (this)
{
foreach (int sample in newSamples)
{
if (!_octet.IsFull)
{
_octet.Add(sample);
}
if (_octet.IsFull)
{
var frame = _octet.ExtractFrame();
frames.Add(frame);
_octet.Reset();
}
}
}
foreach (var frame in frames)
{
this.SendElsewhere(frame)
}
}
there is an error in this program.can anyone fix that?
Error is :TempRecord already defines a member called 'this' with the same parameters value
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
private int[] d= new int[10]{4,5,5,4,4,43,2,2,5,3};
// To enable client code to validate input
// when accessing your indexer.
//public int Length
//{
// get { return temps.Length; }
//}
// Indexer declaration.
// If index is out of range, the temps array will throw the exception.
public float this[int index]
{
get
{
return temps[index];
}
set
{
temps[index] = value;
}
}
public int this[int index]//error:TempRecord already defines a member called 'this' with the same parameters value
{
get
{
return d[index];
}
set
{
d[index] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
TempRecord tempRecord = new TempRecord();
// Use the indexer's set accessor
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
// Use the indexer's get accessor
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
Console.WriteLine(tempRecord[2]);
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}
You have two members named this, that take the same parameters. That's not allowed in C# (or other .Net languages, as far as I'm aware).
You'd think you'd be able to do this if both members return different types, as yours do. But that would present the compiler with ambiguity. Which member would be called if you had code like this?
object x = tempRecord[3];
Make one or both indexers a method.
What you're trying to do is have 2 indexers with the same parameters and different return types. This is not legal in C#. You'll need to move at least one of them into a function
public int GetD(int index) {
return d[index];
}
public void SetD(int index, int value) {
d[index] = value;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 65.9F, 62.1F, 59.2F, 57.5F }; private int[] d = new int[10] { 4, 5, 5, 4, 4, 43, 2, 2, 5, 3 };
public int Length //
{
get { return temps.Length; }
}
public float this[int index]
{
get { return temps[index]; }
set { temps[index] = value; }
}
}
class Program
{
static void Main(string[] args)
{
TempRecord tempRecord = new TempRecord();
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
Console.WriteLine(tempRecord[2]);
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}
If you are trying some concept similar to overloading of functions, I'd like to say it never works with just a change in return type. Similar is the case of data members, where you have tried to use this with the same arguments but different return types.
The best method would be however (even for readability sake) making separate functions for the exclusive events that are being performed above.
I deleted the second data member above, replace it with the something like the foll. I think you better use temprecord.d[index Value] to access & use the member d from main.
public int d[int index]
{
get
{
return d[index];
}
set
{
d[index] = value;
}
}
I need to implement a FIFO queue for messages on a game server so it needs to as fast as possible. There will be a queue for each user.
The queue will have a maxiumem size (lets say 2000). The size won't change during runtime.
I need to prioritize messages ONLY if the queue reaches its maximum size by working backwards and removing a lower priority message (if one exists) before adding the new message.
A priority is an int with possible values of 1, 3, 5, 7, 10.
There can be multiple messages with the same priority.
A message cannot change its priority once allocated.
The application is asynchronous so access to the queue needs to be locked.
I'm currently implementing it using a LinkedList as the underlying storage but have concerns that searching and removing nodes will keep it locked for too long.
Heres the basic code I have at the moment:
public class ActionQueue
{
private LinkedList<ClientAction> _actions = new LinkedList<ClientAction>();
private int _maxSize;
/// <summary>
/// Initializes a new instance of the ActionQueue class.
/// </summary>
public ActionQueue(int maxSize)
{
_maxSize = maxSize;
}
public int Count
{
get { return _actions.Count; }
}
public void Enqueue(ClientAction action)
{
lock (_actions)
{
if (Count < _maxSize)
_actions.AddLast(action);
else
{
LinkedListNode<ClientAction> node = _actions.Last;
while (node != null)
{
if (node.Value.Priority < action.Priority)
{
_actions.Remove(node);
_actions.AddLast(action);
break;
}
node = node.Previous;
}
}
}
}
public ClientAction Dequeue()
{
ClientAction action = null;
lock (_actions)
{
action = _actions.First.Value;
_actions.RemoveFirst();
}
return action;
}
}
A vetted implementation of priority queue for C#/.NET can be found in the C5 Generic Collection Library in the C5.IntervalHeap<T> class.
So we have the following properties:
Priorities are well-defined and bounded
Needs to be thread-safe
Queue size is fixed to 2000 messages, where enqueues beyond this drop the lowest item
Its very easy to write a priority queue which supports all of these properties:
public class BoundedPriorityQueue<T>
{
private object locker;
private int maxSize;
private int count;
private LinkedList<T>[] Buckets;
public BoundedPriorityQueue(int buckets, int maxSize)
{
this.locker = new object();
this.maxSize = maxSize;
this.count = 0;
this.Buckets = new LinkedList<T>[buckets];
for (int i = 0; i < Buckets.Length; i++)
{
this.Buckets[i] = new LinkedList<T>();
}
}
public bool TryUnsafeEnqueue(T item, int priority)
{
if (priority < 0 || priority >= Buckets.Length)
throw new IndexOutOfRangeException("priority");
Buckets[priority].AddLast(item);
count++;
if (count > maxSize)
{
UnsafeDiscardLowestItem();
Debug.Assert(count <= maxSize, "Collection Count should be less than or equal to MaxSize");
}
return true; // always succeeds
}
public bool TryUnsafeDequeue(out T res)
{
LinkedList<T> bucket = Buckets.FirstOrDefault(x => x.Count > 0);
if (bucket != null)
{
res = bucket.First.Value;
bucket.RemoveFirst();
count--;
return true; // found item, succeeds
}
res = default(T);
return false; // didn't find an item, fail
}
private void UnsafeDiscardLowestItem()
{
LinkedList<T> bucket = Buckets.Reverse().FirstOrDefault(x => x.Count > 0);
if (bucket != null)
{
bucket.RemoveLast();
count--;
}
}
public bool TryEnqueue(T item, int priority)
{
lock (locker)
{
return TryUnsafeEnqueue(item, priority);
}
}
public bool TryDequeue(out T res)
{
lock (locker)
{
return TryUnsafeDequeue(out res);
}
}
public int Count
{
get { lock (locker) { return count; } }
}
public int MaxSize
{
get { return maxSize; }
}
public object SyncRoot
{
get { return locker; }
}
}
Supports Enqueue/Dequeue in O(1) time, the TryEnqueue and TryDequeue methods are guaranteed to be thread-safe, and the size of the collection will never exceed the max size you specify in the constructor.
The locks on TryEnqueue and TryDequeue are pretty fine-grained, so you might take a performance hit whenever you need to bulk-load or unload data. If you need to load the queue with a lot of data up front, then lock on the SyncRoot and call the unsafe methods as needed.
If you have a fixed number of priorities, I'd just create a composite Queue class that wraps two or more private Queues.
A drastically simplified example follows although you could expand on it by adding a Priority enum and a switch to determine where to Enqueue an item.
class PriorityQueue {
private readonly Queue normalQueue = new Queue();
private readonly Queue urgentQueue = new Queue();
public object Dequeue() {
if (urgentQueue.Count > 0) { return urgentQueue.Dequeue(); }
if (normalQueue.Count > 0) { return normalQueue.Dequeue(); }
return null;
}
public void Enqueue(object item, bool urgent) {
if (urgent) { urgentQueue.Enqueue(item); }
else { normalQueue.Enqueue(item); }
}
}
I'm assuming you can have duplicate priorities.
There's no container within .NET that allows duplicate keys akin to a C++ multimap. You could do this in a few different ways, either with a SortedList that had an array of values for each priority key (and grab the first item out of that array as the return value); the SortedList is a balanced tree underneath (IIRC) and should give you good insert and retrieval performance.
It really depends on the distribution of queue lengths you are likely to see. 2000 is the max but what's the average and what does the distribution look like? If N is typically small, a simple List<> with a brute force search for next lowest may be a fine choice.
Have you profiled your application to know this is a bottleneck?
"Never underestimate the power of a smart compiler
and a smart CPU with registers and on-chip memory
to run dumb algorithms really fast"