Removing items from a list when a condition is met - c#

I'm writing a multi-threaded download manager where download info is managed by a class I wrote (called DownloadOperation). Downloads are held in a list (called download). I need to remove the objects from the list when a function in the class (queryCompleted) returns true but found out that elements could not be removed from lists from within a foreach loop. What is the best way to have the same effect? I'm relatively new to C# so pardon my stupidity.
private void removeInactiveDownloads()
{
foreach (DownloadOperation dl in download)
{
if (dl.queryComplete() == true)
{
// if download is no longer in progress it is removed from the list.
download.Remove(dl);
}
}
}

List<T> has a method
public int RemoveAll(
Predicate<T> match
)
that removes all elements matching a predicate: http://msdn.microsoft.com/en-us/library/wdka673a.aspx
Therefore I suggest something like:
download.RemoveAll(x => x.queryComplete());
(note that == true is not needed since .queryComplete() already returns true or false!)

Iterate backwards in a For loop instead of a Foreach loop
for(int i = download.Count; i >= 0; i--)
{
if (download[i].queryComplete())
{
// if download is no longer in progress it is removed from the list.
download.RemoveAt(i);
}
}

Patashu's answer is the best solution in general, but based on your example code I would suggest taking another approach altogether.
Are you polling the download list periodically to find the completed ones? Event subscription would probably be a better solution. Since you're new to C#, in case you didn't know the language has built-in support for this pattern: Events
A download could raise a Completed event when it completes, which is subscribed to by the code which manages the list, something like:
private void AddDownload(DownloadOperation dl) {
download.Add(dl);
dl.Completed += (s, e) => download.Remove(dl);
}

Related

Is there a way to await a flag change in a function?

I've attempted to make a simple step mode for an algorithm I'm running, and here is how it looks like:
public async Task<bool> AStarAlgorithmAsync(PFSquare curr = null)
{
// some algorithm code here
foreach(var square in Sorroundings)
{
if (SteppedMode)
{
await Task.Run(Pause);
}
if (await AStarAlgorithmAsync(square))
{
return true;
}
}
}
In my application, I have a Boolean called SteppedMode that decides if the algorithm should run one iteration per click event.
Pause() looks like this:
private void Pause()
{
while (!ContinueStep) { }
ContinueStep = false;
return;
}
And in another part of my (GUI) application I have an event which sets the boolean ContinueStep to true which in theory should end the while loop and continue the algorithm function. Currently this bit of code locks my GUI thread up and I'm almost certain there is a better way to do this.
I'm trying to get my algorithm function to run one iteration, wait for a click from the user and only then continue running the algorithm. Is there an easier and cleaner way to do this?
(This is a GUI application, not a console application.)
Your property is moonlighting as a method.
It makes no sense to set a property, to then have that property revert back to its original state immediately. As a consumer, I would be majorly confused by that behavior. Think about this code:
var myObj = new MyObject();
myObj.MyBoolean = true;
Console.WriteLine(myObj.MyBoolean); // FALSE!?
It just doesn't make sense.
The only effect you want to trigger by setting this property is to execute some code. That's exactly what methods are supposed to be used for:
public void ContinueStep()
{
Console.WriteLine("I did some work");
}
So instead of this:
myObj.ContinueStep = true;
you should be doing this:
myObject.ContinueStep();
This doesn't lock up your UI thread, while also being a lot more sensical to your consumer. The method suggests that some action will be taken (which may or may not lead to state changes in the object - that's a contextual expectation).
Infinite recursion
As an aside; based on your code, AStarAlgorithmAsync is a recursive function, and seemingly infinitely so. There doesn't seem to be an ending condition.
Every recursive level will interate over the first surrounding and then trigger the next level, which again will interate over the first surrounding and then trigger the next level, which again ...
That can't be right, but it's unclear to me how to fix it as the bigger picture is not explained in your question
A simple implementation
What I'm trying to do is get my algorithm function to run one iteration, wait for a click from the user and only then continue running the algorithm, is there an easier and cleaner way to do this?
A simple example of such a thing:
private int _index = 0;
private List<object> _myList = ...; // assume this list contains some elements
public void ProcessNextObject()
{
if(_index < _myList.Length)
{
Process(_myList[_index]);
_index++;
}
}
private void Process(object o)
{
Console.WriteLine("Processing this object!");
}
You can then hook up your click event to call ProcessNextObject().
Note that in this example, the list is processed once and cannot be processed again. By manipulating the index value, you can change that behavior as you like.

Run event once during Update() XNA / C#

this is the best way I can think of doing this. Could you give me so hints as to whether this is the correct way or if there is a more efficient way of doing it.
My situation is:
Each time the frame is Update()'ed (Like in XNA) I want to check if something has happened.. Like if the timer for that screen has been running for over 2000 milliseconds. But I only want it to fire once, not every time the frame is updated. This would cause a problem:
if(totalMilliseconds > 2000)
{
this.Fader.FadeIn();
}
So I came up with this method that I have implemented in the GameScreen class that looks like this:
public bool RunOnce(string Alias, bool IsTrue)
{
if (!this.Bools.ContainsKey(Alias))
this.Bools.Add(Alias, false);
if (IsTrue && !this.Bools[Alias])
{
this.Bools[Alias] = true;
return true;
}
else
return false;
}
This basically checks if the passed if statement boolean is true, if it is then it fires once and not again unless the Bool["Alias"] is set back to false. I use it like this:
if(this.RunOnce("fadeInStarted", totalMilliseconds > 2000))
{
this.Fader.FadeIn();
}
This will then only run one time and I think is quite easily readable code-wise.
The reason I have posted this is for two reasons.. Firstly because I wanted to show how I have overcome the problem as it may be of some help to others who had the same problem.. And secondly to see if I have missed an obvious way of doing this without creating a manual method for it, or if it could be done more efficiently.
Your method is interesting, I don't see a problem with it, you've essentially created a new programming construct.
I haven't encountered this situation a lot so what I have done in this situation is always start with the untidy approach:
bool _hasFadedIn = false;
.
if(totalMilliseconds > 2000 && !_hasFadedIn)
{
this.Fader.FadeIn();
_hasFadedIn = true;
}
And 90% of the time I leave it like that. I only change things if the class starts growing too big. What I would do then is this:
_faderControl.Update(totalMilliseconds);
Put the logic for fader control into a separate class, so:
class FaderControl
{
bool _hasFadedIn=false;
public void Update(int totalMilliseconds)
{
if (_hasFadedIn)
return;
if (totalMilliseconds <= 2000)
return;
this.Fader.FadeIn();
_hasFadedIn=true;
}
}
It can be modified to make it configurable, like reseting, setting "start", "end", fadein time, or also controlling fadeout too.
Here's how I would approach this problem.
These are your requirements:
You have arbitrary pieces of logic which you want to execute inside of your Update().
The logic in question has a predicate associated with it which determines whether the action is ready to execute.
The action should execute at most once.
The core concept here is "action with an associated predicate," so create a data structure which represents that concept:
public class ConditionalAction
{
public ConditionalAction(Action action, Func<Boolean> predicate)
{
this.Action = action;
this.Predicate = predicate;
}
public Action Action { get; private set; }
public Func<Boolean> Predicate { get; private set; }
}
So now, your example becomes
var action = new ConditionalAction(
() => this.Fader.FadeIn(),
() => totalMilliseconds > 2000);
In your Update() you need something that can execute these conditional actions:
public void Update(GameTime time)
{
// for each conditional action that hasn't run yet:
// check the action's predicate
// if true:
// execute action
// remove action from list of pending actions
}
Because their predicates are probably unrelated, actions don't necessarily run in order. So this isn't a simple queue of actions. It's a list of actions from which actions can be removed in arbitrary order.
I'm going to implement this as a linked list in order to demonstrate the concept, but that's probably not the best way to implement this in production code. Linked lists allocate memory on the managed heap, which is generally something to be avoided in XNA. However, coming up with a better data structure for this purpose is an exercise best left for another day.
private readonly LinkedList<ConditionalAction> pendingConditionalActions =
new LinkedList<ConditionalAction>();
public void Update(GameTime time)
{
for (var current = pendingConditionalActions.First; current != null; current = current.Next)
{
if (current.Value.Predicate())
{
current.Value.Action();
pendingConditionalActions.Remove(current);
}
}
}
public void RegisterConditionalAction(ConditionalAction action)
{
pendingConditionalActions.AddLast(action);
}
Registered actions will wait until their predicates become true, at which point they will be executed and removed from the list of pending actions, ensuring that they only run once.

Share a List<T> between multiple threads

Am I right in saying that I only need to use lock to Add/Remove/Change the List, or do I also need to lock it when iterating over it?
So am I thread safe by doing this:
class ItemsList
{
List<int> items = new List<int>();
object listLock = new object();
public void Add(int item)
{
lock (listLock)
{
items.Add(item);
}
}
public void Remove(int item)
{
lock (listLock)
{
items.Remove(item);
}
}
public void IncrementAll()
{
foreach (var item in items)
{
item += 1;
}
}
}
You should definitely lock when iterating over it too - if the list is changed while you're iterating over it, an exception will be thrown.
From the docs for List<T>.GetEnumerator:
The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.
Additionally, even a single read from a List<T> isn't thread-safe if you could be writing to it as well - even if it doesn't fail, there's no guarantee that you'll get the most recent value.
Basically, List<T> is only safe for multiple threads if it's not written to after the last point at which its state becomes visible to all threads.
If you want a thread-safe collection, and if you're using .NET 4 or higher, take a look at the System.Collections.Concurrent namespace.
List<T> is not thread-safe generally. Having multiple readers will not cause any issues, however, you cannot write to the list while it is being read. So you would need to lock on both read and write or use something like a System.Threading.ReaderWriterLock (which allows multiple readers but only one writer). If you are developing under .NET 4.0 or bigger, you could use a BlockingCollection instead, which is a thread safe collection.
No, that isn't safe. You will get a "collection was modified" kind of exception if another thread modifies it while you are reading it.
The most efficient way to fix this is to use a ReaderWriterLockSlim to control access, so that multiple threads can be reading it simultaneously, and it will only get locked when something tries to modify it.
You're not even thread safe with what you have if you never iterate it.
You need to define what types of operations you are doing with the data structure before we can discuss whether or not it will work as intended.
In the general case though, you do need to lock while reading. As it is, someone could add an item while you're in the middle of iterating and it would break all kinds of things. Even reading a single item could be broken if you added an item in the middle of the read.
Also note that this would, at best, make each operation logically atomic. If you're ever performing multiple operations and making assumptions about the state of the data structure then that won't be enough.
In many cases, to resolve this issue, you need to do your locking on the caller side, rather than just wrapping each operation in a lock.
You should probably use a ReaderWriterLockSlim so that multiple threads can read the collection, but only one can modify it.
On IncrementAll you will catch InvalidOperationException because of the changes, made in collection. You can see it in test unit, like this:
ItemsList il = new ItemsList();
Task ts = new Task(() =>
{
for (int i = 0; i < 100000; i++)
{
il.Add(i);
System.Threading.Thread.Sleep(100);
}
}
);
ts.Start();
Task ts2 = new Task(() =>
{
//DoSomeActivity
il.IncrementAll();
}
);
ts2.Start();
Console.Read();
Iteration must be locked also!!!
You might want to take a look at ConcurrentQueue<>();
This is basically a thread safe list (As far as i'm aware), that's rather handy. You can use it a bit like this;
public ConcurrentQueue<yourType> alarmQueue = new ConcurrentQueue<yourType>();
System.Timers.Timer timer;
public QueueManager()
{
timer = new System.Timers.Timer(1000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
DeQueueAlarm();
}
private void DeQueueAlarm()
{
yourType yourtype;
while (alarmQueue.TryDequeue(out yourtype))
{
//dostuff
}
}
edit: Just as John said, this is available in .Net4 onwards. Read more here; http://msdn.microsoft.com/en-us/library/dd267265.aspx

Safe way to call a method for each element of a set that modifies said set?

I've got a class defined like this (relevant methods shown):
class ShaderProgram : IDisposable
{
private HashSet<Shader> _shaders = new HashSet<Shader>();
public void AttachShader(Shader shader)
{
GL.AttachShader(Handle, shader.Handle);
_shaders.Add(shader);
}
public void DetachShader(Shader shader)
{
GL.DetachShader(Handle, shader.Handle);
_shaders.Remove(shader);
}
}
Now I'm trying to figure out how to write the Dispose method, I thought I could do it like this:
public void Dispose()
{
foreach(var shader in _shaders)
DetachShader(shader);
GL.DeleteProgram(Handle);
}
But now I suspect that's unsafe because I'm iterating over a set and deleting from it at the same time... if it were a queue or stack Id just say "while not empty, pop one off and delete it", but since it's a HashSet... I'm not sure what the best approach is. How should I handle this?
Edit: The point is to avoid code duplication; I want to call ShaderProgram.DetachShader for each element. I know I can repeat the code inside that function and then clear the whole set at the end -- that's not what I want to do.
Occurs to me now, that I don't really have to empty the HashSet at all, do I? The ShaderProgram object is about to be destroyed anyway, all I need to do is clean up any unmanaged resources, and the C# GC can clean up the rest, right?
public void Dispose()
{
foreach (var shader in _shaders)
GL.DetachShader(Handle, shader.Handle);
GL.DeleteProgram(Handle);
}
That said, I still want answers to the original question. My goal here is not to solve a very simple problem, but to learn the best approach to this class of problem.
There's no problem in doing this, but maybe you should consider to iterate your set, detach your shader from your GL variable and then just clear your HashSet. If you don't want to duplicate code that's in your own detach method you should split that one up and let it be called from those 2 places.
How about some LINQ:
while (_shaders.Any()) {
DetachShader(_shaders.First());
}
This wouldn't work in general, though, because you could end up calling the function on the same element multiple times. It only makes sense if the function is removing the element from the underlying collection.
In the general case, where the function doesn't modify the collection, you could use something like this:
while (hashset.Any()) {
var item = hashset.First();
Process(item);
hashset.Remove(item);
}
Or this:
foreach (var item in hashset) {
Process(item);
}
hashset.Clear();
Update: As pointed out by #SLaks in the comments, calling First() for every element in the hash set as it's emptied is O(n^2). This doesn't matter for tiny collections, but could make a world of difference if you have a large collection.
I do not understand how come someone with 17k reputation is asking this. Am I missing something?
public void Dispose()
{
foreach(var shader in _shaders)
GL.DetachShader( Handle, shader.Handle );
_shaders.Clear();
}
If your collection is very small I would use:
foreach (var item in set.ToArray())
set.Remove(item);
Another solution would be the RemoveWhere() method:
set.RemoveWhere(item =>
{
Console.WriteLine(item);
return true;
});

Multi-threading problem when checking the list Count property

I have List newJobs. Some threads add items to that list and other thread removes items from it, if it's not empty. I have ManualResetEvent newJobEvent which is set when items are added to the list, and reset when items are removed from it:
Adding items to the list is performed in the following way:
lock(syncLock){
newJobs.Add(job);
}
newJobEvent.Set();
Jobs removal is performed in the following way:
if (newJobs.Count==0)
newJobEvent.WaitOne();
lock(syncLock){
job = newJobs.First();
newJobs.Remove(job);
/*do some processing*/
}
newJobEvent.Reset();
When the line
job=newJobs.First()
is executed I sometimes get an exception that the list is empty. I guess that the check:
if (newJobs.Count==0)
newJobEvent.WaitOne();
should also be in the lock statement but I'm afraid of deadlocks on the line newJobEvent.WaitOne();
How can I solve it?
Many thanks and sorry for the long post!
You are right. Calling WaitOne inside a lock could lead to a deadlock. And the check to see if the list is empty needs to be done inside the lock otherwise there could be a race with another thread trying to remove an item. Now, your code looks suspiciously like the producer-consumer pattern which is usually implemented with a blocking queue. If you are using .NET 4.0 then you can take advantage of the BlockingCollection class.
However, let me go over a couple of ways you can do it youself. The first uses a List and a ManualResetEvent to demonstrate how this could be done using the data structures in your question. Notice the use of a while loop in the Take method.
public class BlockingJobsCollection
{
private List<Job> m_List = new List<Job>();
private ManualResetEvent m_Signal = new ManualResetEvent(false);
public void Add(Job item)
{
lock (m_List)
{
m_List.Add(item);
m_Signal.Set();
}
}
public Job Take()
{
while (true)
{
lock (m_List)
{
if (m_List.Count > 0)
{
Job item = m_List.First();
m_List.Remove(item);
if (m_List.Count == 0)
{
m_Signal.Reset();
}
return item;
}
}
m_Signal.WaitOne();
}
}
}
But this not how I would do it. I would go with the simplier solution below with uses Monitor.Wait and Monitor.Pulse. Monitor.Wait is useful because it can be called inside a lock. In fact, it is suppose to be done that way.
public class BlockingJobsCollection
{
private Queue<Job> m_Queue = new Queue<Job>();
public void Add(Job item)
{
lock (m_Queue)
{
m_Queue.Enqueue(item);
Monitor.Pulse(m_Queue);
}
}
public Job Take()
{
lock (m_Queue)
{
while (m_Queue.Count == 0)
{
Monitor.Wait(m_Queue);
}
return m_Queue.Dequeue();
}
}
}
Not answering your question, but if you are using .NET framework 4, you can use the new ConcurrentQueue which does all the locking for you.
Regarding your question:
One scenario that I can think of causing such a problem is the following:
The insertion thread enters the lock, calls newJob.Add, leaves the lock.
Context switch to the removal thread. It checks for emptyness, sees an item, enters the locked area, removes the item, resets the event - which hasn't even been set yet.
Context switch back to the insertion thread, the event is set.
Context switch back to the removal thread. It checks for emptyness, sees no items, waits for the event - which is already set, trys to get the first item... Bang!
Set and reset the event inside the lock and you should be fine.
I don't see why object removal in case of zero objects should wait for one to be added and then remove it. It looks to be being against logic.

Categories