BeginInvoke causes error due to skipped null check - c#

I encountered a to me not understandable error caused by using Dispatcher.BeginInvoke within a multi-threaded application.
My program contains a List of objects through which I loop using multiple threads and perform some calculations.
I have simplified (and slightly modified) my code structure to the very bare essentials, so it will hopefully be easier to understand:
public class Foo
{
public void DoCalc()
{
//do calculations
}
}
public class Foo2
{
public Foo foo = new Foo();
public Ellipse ellipse;
}
public partial class MainWindow : Window
{
List<Foo2> myList = new List<Foo2>();
List<Tuple<int, int>> indicesList = new List<Tuple<int, int>>();
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 10; ++i)
myList.Add(new Foo2 { ellipse = new Ellipse() });
for (int i = 10; i < 20; ++i)
myList.Add(new Foo2());
indicesList.Add(new Tuple<int, int>(0, 9));
indicesList.Add(new Tuple<int, int>(10, 19));
}
private void OnStart(object sender, RoutedEventArgs e)
{
foreach (var t in indicesList)
ThreadPool.QueueUserWorkItem(new WaitCallback(Loop), t);
}
private void Loop(object o)
{
Tuple<int, int> indices = o as Tuple<int, int>;
for(int i = indices.Item1; i <= indices.Item2; ++i)
{
myList[i].foo.DoCalc();
if (myList[i].ellipse == null)
continue;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => myList[i].ellipse.Fill = Brushes.Black));
}
}
}
The first half of items in myList has ellipse point to actual objects, while the second half points to null. Within Loop I check at every iteration if ellipse is null and skip that iteration if necessary. What is weird is that in the second thread where all ellipses point to null, the program still ends up calling the BeginInvoke action on the first item (index 10), causing the program to crash, due to a null reference exception.
If I put a breakpoint on the line myList[i].foo.DoCalc(); and go through the program slowly step by step, no error occurs. Also when I change BeginInvoke to Invoke no error occurs.
As I understand, BeginInvoke works asynchronously by sending a request to the Dispatcher to be performed at some point, while Invoke blocks the calling thread until the Dispatcher has performed the request. However, since I neither access the same elements in the two loops, nor do I change anything about the list itself, so I don't understand how multithreading or the asynchronous nature of BeginInvoke could in any way interfere with what I am doing here.
Unfortunately, I have only found BeginInvoke errors connected with Lists when adding or removing items on SO, however, nothing where an error occurs when all threads seem to access different items at all times. If my code has some fundamental issues that I do simply not understand (which might cause my program to actually not function), then please clear this up for me or send me a link to an answer, I couldn't find. I have been stuck with this issue for a whole day now!

You are running in to variable capture. The i that gets used in the invoke call will likely be indices.Item2 + 1 not the i value that it had at the time you did the BeginInvoke. You must copy i in to a local variable that is created new each loop itteration.
private void Loop(object o)
{
Tuple<int, int> indices = o as Tuple<int, int>;
for(int i = indices.Item1; i <= indices.Item2; ++i)
{
myList[i].foo.DoCalc();
if (myList[i].ellipse == null)
continue;
int iLocal = i;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => myList[iLocal].ellipse.Fill = Brushes.Black));
}
}
foreach prior to C# 5 had the same issue, see here for more info.

This could have something to do with closures...
Try this:
var current = myList[i].foo.DoCalc();
if (current.ellipse == null)
continue;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() => current.ellipse.Fill = Brushes.Black));

Related

Speed improvement using multiple threads

I have a CustomControl called PlaylistView. It displays elements in a playlist with name and thumbnail. The method DisplayPlaylist ensures that a thread is started, in which the individual elements are added one by one and the thumbnails (30th frame) are read out:
public void DisplayPlaylist(Playlist playlist)
{
Thread thread = new Thread(() => DisplayElements(playlist));
thread.Start();
}
private void DisplayElements(Playlist playlist)
{
for (int i = 0; i < playlist.elements.Count; i++)
DisplayElement(playlist.elements[i], i);
}
private void DisplayElement(IPlayable element, int index)
{
VideoSelect videoSelect = null;
if (element is Audio)
//
else if (element is Video)
videoSelect = new VideoSelect(index, element.name, GetThumbnail(element.path, SystemData.thumbnailFrame));
videoSelect.Location = GetElementsPosition(index);
panel_List.BeginInvoke(new Action(() =>
{
panel_List.Controls.Add(videoSelect);
}));
}
private Bitmap GetThumbnail(string path, int frame)
{
VideoFileReader reader = new VideoFileReader();
try
{
reader.Open(path);
for (int i = 1; i < frame; i++)
reader.ReadVideoFrame();
return reader.ReadVideoFrame();
}
catch
{
return null;
}
}
But there is a problem.
It is much too slow (about 10 elements/sec). With a playlist length of 614, you would have to wait more than a minute until all are displayed. Each time you change the playlist, such as adding or deleting an item, the procedure starts with the new item. Adding 2 or more will make it even more complicated.
I now had the approach to use multiple threads and the number of threads used for this to be specified by the user (1 to max 10). The implementation in the code currently looks like this (only changed parts compared to the previously posted code)
public void DisplayPlaylist(Playlist playlist)
{
for (int i = 0; i < SystemData.usedDisplayingThreads; i++)
{
Thread thread = new Thread(() => DisplayElements(playlist, i));
thread.Start();
}
}
private void DisplayElements(Playlist playlist, int startIndex)
{
for (int i = startIndex; i < playlist.elements.Count; i += SystemData.usedDisplayingThreads)
DisplayElement(playlist.elements[i], i);
}
The problem is that now very often null is returned by the GetThumbnail function, so an error occurs. In addition, a System.AccessViolationException is often thrown out.
In my opinion, the reason for this is the presence of multiple, simultaneously active VideoFileReaders. However, I do not know what exactly triggers the problem so I cannot present any solution. Maybe you know what the actual trigger is and how to fix the problem or maybe you also know other methods for speed improvement, which maybe even more elegant.
I would start with logging what exception is raised in GetThumbnail method. Your code hides it and returns null. Change to catch (Exception exc), write exception details in log or at least evaluate in debugger. That can give a hint.
Also I'm pretty sure your VideoFileReader instances are IDisposable, so you have to dispose them by invoking reader.Close(). Maybe previous instances were not disposed and you are trying to open same file multiple times.
Update: video frame has to be disposed as well. Probably you will need to do a copy of bitmap if it is referenced with reader and prevents disposion.

Batch updating UI component through observable collection with large amounts of data WinRT

I have an WinRT application that fires notifications everytime it recieves data from a device. I also have a UI control that is databound to an observable collection which I wish to add the new data to
While I have made it capable of updating the observable collection, it causes the UI to become very laggy, as the amount of data generated it fast. It would therefore be better to batch the update, maybe every few hundred milliseconds.
Below shows a snippet of the code. First I create the periodic timer
TimerElapsedHandler f = new TimerElapsedHandler(batchUpdate);
CreatePeriodicTimer(f, new TimeSpan(0, 0, 3));
Below is my event handler for when new data comes in, along with the temporary list that stores the information
List<FinancialStuff> lst = new List<FinancialStuff>();
async void myData_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
var data = new byte[args.CharacteristicValue.Length];
DataReader.FromBuffer(args.CharacteristicValue).ReadBytes(data);
lst.Add(new FinancialStuff() { Time = "DateTime.UtcNow.ToString("mm:ss.ffffff")", Amount = data[0] });
}
Then my batch update, which is called peroidically
private void batchUpdate(ThreadPoolTimer source)
{
AddItem<FinancialStuff>(financialStuffList, lst);
}
Then finally, for testing I want to clear the observable collection and items.
public async void AddItem<T>(ObservableCollection<T> oc, List<T> items)
{
lock (items)
{
if (Dispatcher.HasThreadAccess)
{
foreach (T item in items)
oc.Add(item);
}
else
{
Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
{
oc.Clear();
for (int i = 0; i < items.Count; i++)
{
items.Count());
oc.Add(items[i]);
}
lst.Clear();
});
}
}
}
While this seems to work, after a few updates the UI locks up and it updates very slowly/if not at all. For testing, it's only getting a few hundred items in the list by the time the timer is fired.
Can anybody enlighten me as to why as to why this is happening - I'm presuming my design is very poor.
Thanks
You're not locking your list in the event handler
// "lst" is never locked in your event handler
List<FinancialStuff> lst = new List<FinancialStuff>();
lst.Add(new FinancialStuff() { Time = "DateTime.UtcNow.ToString("mm:ss.ffffff")", Amount = data[0] });
Passing "lst" above to your async method
AddItem<FinancialStuff>(financialStuffList, lst);
You're locking "items" below, which is really "lst" above. However, you're adding to the list while your processing it. I assume the event handler has a higher priority so your processing is slower than your add. This can lead to "i < items.Count" being true forever.
public async void AddItem<T>(ObservableCollection<T> oc, List<T> items)
{
// "lst" reference is locked here, but it wasn't locked in the event handler
lock (items)
{
if (Dispatcher.HasThreadAccess)
{
foreach (T item in items)
oc.Add(item);
}
else
{
Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
{
oc.Clear();
// This may never exit the for loop
for (int i = 0; i < items.Count; i++)
{
items.Count());
oc.Add(items[i]);
}
lst.Clear();
});
}
}
}
EDIT:
Do you need to view every piece of data? There is going to be some overhead when using a lock. If you're getting data quicker than the speed of how fast you can render it, you'll eventually be backed up and/or have a very large collection to render, which might also cause some problems. I suggest you do some filtering to only draw the last x number of items (say 100). Also, I'm not sure why you need the if (Dispatcher.HasThreadAccess) condition either.
Try the following:
public async void AddItem<T>(ObservableCollection<T> oc, List<T> items)
{
// "lst" reference is locked here, but it wasn't locked in the event handler
lock (items)
{
// Change this to what you want
const int maxSize = 100;
// Make sure it doesn't index out of bounds
int startIndex = Math.Max(0, items.Count - maxSize);
int length = items.Count - startIndex;
List<T> itemsToRender = items.GetRange(startIndex, length);
// You can clear it here in your background thread. The references to the objects
// are now in the itemsToRender list.
lst.Clear();
// Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
// Please verify this is the correct syntax
Dispatcher.Run(() =>
{
// At second look, this might need to be locked too
// EDIT: This probably will just add overhead now that it's not running async.
// You can probably remove this lock
lock(oc)
{
oc.Clear();
for (int i = 0; i < itemsToRender.Count; i++)
{
// I didn't notice it before, but why are you checking the count again?
// items.Count());
oc.Add(itemsToRender[i]);
}
}
});
}
}
EDIT2:
Since your AddItem method is already on a background thread, I don't think you need to run the Dispatcher.RunAsync. Instead, I think it might be desirable for it to block so you don't end up with multiple calls to that section of code. Try using Dispatcher.Run instead. I've updated the code example above to show the changes. You shouldn't need the lock on the oc anymore since the lock on the items is good enough. Also, verify the syntax for Dispatcher.Run is correct.

LinkedList modified, Thread crashing the program

My problem is a synchronization problem with a thread and the user simultaneously accessing and modifying a LinkedList.
I’m making a program in C# that will display some messages in a panel. I’m getting an error called “The collection was modified after the enumerator was instantiated.”, that is because I’m adding or removing messages while a thread is accessing the LinkedList.
I have read some solutions but I am still unable to make them work. I’m using an Enumerator for the thread work in my LinkedList. I tried to make some locks in my code so the thread would not iterate the list while I remove or add an element. I also tried to lock the thread for the operations on my list. But all my attempts failed.
Here is some code of my project. This one is for adding a message:
public void addMsg(MsgForDisplay msg) {
Label lbl = new Label();
lbl.Text = (msg.getMsgText() + " -");
lbl.ForeColor = color;
lbl.Font = textFont;
lbl.BackColor = backg;
lbl.Visible = true;
lbl.AutoSize = true;
lbl.Location = new Point(width(), 0);
//lock(labels) { tried to lock here but failed
labels.AddLast(lbl);
lastLb = lbl;
this.Controls.Add(lbl);
this.Refresh();
//}
}
Removing a message:
public void removeMsg(string msg) {
string remove = msg + " -";
Label lbRemove = null;
//lock(labels) { also tried to lock here
var it = labels.GetEnumerator();
while(it.MoveNext()) {
Label label = it.Current;
if (label.Text.Equals(remove)) {
lbRemove = label;
}
}
labels.Remove(lbRemove);
this.Controls.Remove(lbRemove);
this.Refresh();
//}
}
And there is the problem, in my thread:
public void run() {
while (true) {
// lock (labels) { also tried to lock here
var it = labels.GetEnumerator();
while (it.MoveNext()) { // the crash occurs here
Label lb = it.Current;
if (lb.Location.X + lb.Width < 0) {
this.Invoke(new MethodInvoker(() => { this.Controls.Remove(lb); }));
if (labels.Count > 1)
this.Invoke(new MethodInvoker(() => { lb.Location = new Point(lastLb.Right, 0); }));
else
this.Invoke(new MethodInvoker(() => { lb.Location = new Point(2000, 0); }));
lastLb = lb;
this.Invoke(new MethodInvoker(() => { this.Controls.Add(lb); }));
this.Invoke(new MethodInvoker(() => { this.Refresh(); }));
}
if (leftLb != null)
if (leftLb.Location.X + leftLb.Width - lb.Location.X < -20)
this.Invoke(new MethodInvoker(() => { lb.Location = new Point(leftLb.Right, 0); }));
else
this.Invoke(new MethodInvoker(() => { lb.Location = new Point(lb.Location.X - 3, lb.Location.Y); }));
leftLb = lb;
}
System.Threading.Thread.Sleep(30);
// }
}
}
As you can see I’m using an GetEnumerator of my labels, what in Java should be the Iterator. With this I shouldn’t be able to iterate the list without problem when the user add or remove messages?
Is there a way to synchronize the accesses to the list?
EDIT: I have tried the ConcurrentBag and ConcurrentDictionary but without any improvement to the project as you can see in the comments…
Please before you post an answer read the comments bellow to make sure that you know what is going on.
EDIT: Tried to add a mutex to my code for addMsg and removeMsg but still crashing. If I use the mutex in the thread it will be slowed down.
I created a Timer in step of the thread and that solved the crashing problem. Here is the code if you want to see it.
private System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
private void startThread() {
myTimer.Tick += new EventHandler(timerEvent);
myTimer.Interval = 30;
myTimer.Start();
}
private void timerEvent(object sender, EventArgs e) {
var it = labels.GetEnumerator();
while (it.MoveNext()) {
Label lb = it.Current;
// Label lb = labels.ElementAt(b);
if (lb.Location.X + lb.Width < 0) {
this.Controls.Remove(lb);
if (labels.Count > 1)
lb.Location = new Point(lastLb.Right, 0);
else
lb.Location = new Point(2000, 0);
lastLb = lb;
this.Controls.Add(lb);
this.Refresh();
}
if (leftLb != null)
if (leftLb.Location.X + leftLb.Width - lb.Location.X < -20)
lb.Location = new Point(leftLb.Right, 0);
else
lb.Location = new Point(lb.Location.X - 3, lb.Location.Y);
leftLb = lb;
}
}
The source of your problem is that while you are iterating over the list of labels You call either Remove or Add functions which modifies this list whis is not allowed while iterating over it. Instead of this
var it = labels.GetEnumerator();
while (it.MoveNext()) // the crash occurs here
I suggest something like that:
for(int i = 0; i < labels.Count; i++)
{
labels.remove(labels[i]); //this is valid of course the count of the list will change
//Here you can add or remove elements from the labels
}
Or you can try first to collect the removable items into a temporal list and later remove it from the original.
As others have already stated, the problem is you are modifying the collection while enumerating over it.
Now, the easiest workaround is obviously not to enumerate over the same collection that is being modified. And how do you do that? Simple, you just clone the collection, and iterate over it:
lock (labels)
{
var clone = new LinkedList<Label>(labels);
it = labels.GetEnumerator();
}
Now you can enumerate over it safely, without worrying about inconsistencies.
A few notes:
I am using a lock, because the cloning also must enumerate over your collection, and while it does it in a very short time, it is still required for synchronization. Off course, you need to uncomment the locks you've already added to addMsg and removeMsg.
The reason that locking your whole loop didn't work, is that when you call Invoke, you are essentially returning control to the thread that owns the object (the main GUI thread in this case). The problem is, that this thread is already stuck on handling whatever event caused addMsg or removeMsg to be called, leading to a deadlock.
You should also note that cloning a collection every 30 ms, isn't exactly efficient, and shouldn't be used in a production code, but given that this probably just an exercise, it should suffice. In real life, you should probably use a separate collection for the changes you are about to do (adding or removing labels), change this collection in addMsg and removeMsg, and then merge the changes to labels inside your thread, but outside of the iteration over the labels.
Not directly related to your question, but still: you should use a foreach loop instead of directly creating an enumerator object in C#.
As stated before, changing any collection while enumerating it, results in an exception in .Net. You can avoid this by using for or while loops.
However I don't see the point in using a Linked List in this scenario. It should be way simpler and more performant to use a ConcurrentDictionary and just add or remove the requested item. There is also a ObservableConcurrentDictionary available, although not part of the Framework. It is very stable, in my experience.
http://www.codeproject.com/Articles/208361/Concurrent-Observable-Collection-Dictionary-and-So

Starting two threads runs them in sequence and not at the same time

I have a main thread which is controlling a windows form, upon pressing a button two threads are executed. One is used for recording information, the other is used for reading it. The idea behind putting these in threads is to enable the user to interact with the interface while they are executing.
Here is the creating of the two threads;
Thread recordThread = new Thread(() => RecordData(data));
recordThread.Name = "record";
recordThread.Start();
Thread readThread = new Thread(() => ReadData(data));
readThread.Name = "read";
readThread.Start();
The data is simply a Data-object that stores the data that is recorded during the recording.
The problem that I am facing is that the first thread is executed fine, the second refuses to run until the first one completes. Putting a breakpoint in the second threads function, ReadData lets me know that it is only called after the first thread is done with all of its recording.
I have been trying to solve this for a few hours now and I can't get my head around why it would do this. Adding a;
while(readThread.IsAlive) { }
right after the start will halt the execution of anything after that, and it's state is Running. But it will not go to the given method.
Any ideas?
Edit:
The two functions that are called upon by the threads are;
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
d.AddData(data);
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
double[] data = d.ReadLastData();
this.Invoke(updateData, new object[] { data });
i++;
}
}
The data object has locking in both the functions that are called upon; ReadLastData and Read.
Here are the methods in the Data object.
public void AddData(double[] data)
{
lock (this)
{
int i = 0;
foreach (double d in data)
{
movementData[i].Add(d);
i++;
}
}
}
public double[] ReadLastData()
{
double[] data = new double[channels];
lock (this)
{
int i = 0;
foreach (List<double> list in movementData)
{
data[i] = list[list.Count - 1];
}
}
return data;
}
Looks like you have a race condition between your reading/writing. In your first thread you lock down the object whilst you add data to it and in the second thread you attempt to get an exclusive lock on it to start reading. However, the problem is the first thread is executing so fast that the second thread never really gets a chance to acquire the lock.
The solution to this problem really depends on what sort of behaviour you are after here. If you expect after every write you get a consecutive read then what you need to do is control the execution between the reading/writing operations e.g.
static AutoResetEvent canWrite = new AutoResetEvent(true); // default to true so the first write happens
static AutoResetEvent canRead = new AutoResetEvent(false);
...
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
canWrite.WaitOne(); // wait for the second thread to finish reading
d.AddData(data);
canRead.Set(); // let the second thread know we have finished writing
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
canRead.WaitOne(); // wait for the first thread to finish writing
double[] data = d.ReadLastData();
canWrite.Set(); // let the first thread know we have finished reading
this.Invoke(updateData, new object[] { data });
i++;
}
}
Could you try adding a Sleep inside RecordData?
Maybe it's just your (mono cpu??) windows operating system that doesn't let the second thread get its hand on cpu resources.
Don't do this:
lock (this)
Do something like this instead:
private object oLock = new object();
[...]
lock (this.oLock)
EDIT:
Could you try calls like this:
Thread recordThread = new Thread((o) => RecordData((Data)o));
recordThread.Name = "record";
recordThread.Start(data);

Is yield return in C# thread-safe?

I have the following piece of code:
private Dictionary<object, object> items = new Dictionary<object, object>;
public IEnumerable<object> Keys
{
get
{
foreach (object key in items.Keys)
{
yield return key;
}
}
}
Is this thread-safe? If not do I have to put a lock around the loop or the yield return?
Here is what I mean:
Thread1 accesses the Keys property while Thread2 adds an item to the underlying dictionary. Is Thread1 affected by the add of Thread2?
What exactly do you mean by thread-safe?
You certainly shouldn't change the dictionary while you're iterating over it, whether in the same thread or not.
If the dictionary is being accessed in multiple threads in general, the caller should take out a lock (the same one covering all accesses) so that they can lock for the duration of iterating over the result.
EDIT: To respond to your edit, no it in no way corresponds to the lock code. There is no lock automatically taken out by an iterator block - and how would it know about syncRoot anyway?
Moreover, just locking the return of the IEnumerable<TKey> doesn't make it thread-safe either - because the lock only affects the period of time when it's returning the sequence, not the period during which it's being iterated over.
Check out this post on what happens behind the scenes with the yield keyword:
Behind the scenes of the C# yield keyword
In short - the compiler takes your yield keyword and generates an entire class in the IL to support the functionality. You can check out the page after the jump and check out the code that gets generated...and that code looks like it tracks thread id to keep things safe.
OK, I did some testing and got an interesting result.
It seems that it is more an issue of the enumerator of the underlying collection than the yield keyword. The enumerator (actually its MoveNext method) throws (if implemented correctly) an InvalidOperationException because the enumeration has changed. According to the MSDN documentation of the MoveNext method this is the expected behavior.
Because enumerating through a collection is usually not thread-safe a yield return is not either.
I believe it is, but I cannot find a reference that confirms it. Each time any thread calls foreach on an iterator, a new thread local* instance of the underlying IEnumerator should get created, so there should not be any "shared" memory state that two threads can conflict over...
Thread Local - In the sense that it's reference variable is scoped to a method stack frame on that thread
I believe yield implementation is thread-safe. Indeed, you can run that simple program at home and you will notice that the state of the listInt() method is correctly saved and restored for each thread without edge effect from other threads.
public class Test
{
public void Display(int index)
{
foreach (int i in listInt())
{
Console.WriteLine("Thread {0} says: {1}", index, i);
Thread.Sleep(1);
}
}
public IEnumerable<int> listInt()
{
for (int i = 0; i < 5; i++)
{
yield return i;
}
}
}
class MainApp
{
static void Main()
{
Test test = new Test();
for (int i = 0; i < 4; i++)
{
int x = i;
Thread t = new Thread(p => { test.Display(x); });
t.Start();
}
// Wait for user
Console.ReadKey();
}
}
class Program
{
static SomeCollection _sc = new SomeCollection();
static void Main(string[] args)
{
// Create one thread that adds entries and
// one thread that reads them
Thread t1 = new Thread(AddEntries);
Thread t2 = new Thread(EnumEntries);
t2.Start(_sc);
t1.Start(_sc);
}
static void AddEntries(object state)
{
SomeCollection sc = (SomeCollection)state;
for (int x = 0; x < 20; x++)
{
Trace.WriteLine("adding");
sc.Add(x);
Trace.WriteLine("added");
Thread.Sleep(x * 3);
}
}
static void EnumEntries(object state)
{
SomeCollection sc = (SomeCollection)state;
for (int x = 0; x < 10; x++)
{
Trace.WriteLine("Loop" + x);
foreach (int item in sc.AllValues)
{
Trace.Write(item + " ");
}
Thread.Sleep(30);
Trace.WriteLine("");
}
}
}
class SomeCollection
{
private List<int> _collection = new List<int>();
private object _sync = new object();
public void Add(int i)
{
lock(_sync)
{
_collection.Add(i);
}
}
public IEnumerable<int> AllValues
{
get
{
lock (_sync)
{
foreach (int i in _collection)
{
yield return i;
}
}
}
}
}

Categories