Забавно, я собирался протестировать захоронение и параллелизм, и во время своей простой настройки я подумал, какого чёрта, действительно ли это стоит того. Но теперь, после 45 минут настройки некоторых глупых тестовых классов, я столкнулся с первой ошибкой, которую я не понимаю.
Кажется, мне нужно немного больше попрактиковаться в списках, блокировках и потоках.
Кто-нибудь знает, почему это вызывает исключение недопустимой операции (см. Прикрепленный код).
Для тех, кому нравится опыт F5, вот полное решение (300 КБ)
http://www.filesavr.com/TXXXFVE40GTJK43
Не открывайте представления, они могут привести к сбою вашего VS2010. И вам нужны инструменты WP7, извините, хотя я почти уверен, что этот пример будет работать (не работать) и на чистом C #.
[EDIT]
Я обновляю ссылку, теперь она работает (со старым кодом)
И я нашел первую ошибку, благодаря комментарию.
Это работает:
private void IncOneWithLock()
{
lock (CounterListOne)
{
IncListOne();
}
}
private void IncListOne()
{
if (CounterListOne == null)
{
Log("CounterListOne == null");
return;
}
var c = 0;
var oldList = CounterListOne.ToList();
foreach (var i in oldList)
{
CounterListOne[c++] = i + 1;
Thread.Sleep(Next(80*DelayFactor, 150*DelayFactor));
}
}
Будет продолжать тестирование надгробных материалов и публиковать возможные вопросы в следующей ветке. Изменение списка во время итерации - привет новичку ошибка: -)
[/ EDIT]
Для вашего удобства ожидание происходит в этой функции, и это неправильное ожидание операции:
private void IncOneWithLock()
{
if (CounterListOne == null)
{
Log("CounterListOne == null");
return;
}
lock (this)
{
var c = 0;
foreach (var i in CounterListOne)
{
CounterListOne[c++] = i + 1;
Thread.Sleep(Next(80 * DelayFactor, 150 * DelayFactor));
}
}
}
Вот полный источник класса теста:
public class CounterClass : TestBase
{
private DispatcherTimer _dT;
public int CounterA { get; set; }
public ObservableCollection<int> CounterListOne { get; set; }
public List<int> CounterListTwo { get; set; }
public List<int> CounterListThree { get; set; }
private const int DelayFactor = 10;
public CounterClass()
{
CounterListOne = new ObservableCollection<int>();
CounterListTwo = new List<int>();
CounterListThree = new List<int>();
InitCounterLists();
StartBackgroundLogger();
}
public void LogLists()
{
lock (this)
//lock (CounterListTwo)
// lock (CounterListThree)
{
Log("====================================================");
Log("CounterListOne " + String.Join("-", CounterListOne.Select(x => x.ToString()).ToArray()));
Log("CounterListTwo " + String.Join("-", CounterListTwo.Select(x => x.ToString()).ToArray()));
Log("CounterListThree " + String.Join("-", CounterListThree.Select(x => x.ToString()).ToArray()));
Log("====================================================");
}
}
public void RunTests()
{
Log("MultiIncWithoutLocks");
//MultiIncWithoutLocks();
Log("MultiIncWithLocks");
MultiIncWithLocks();
}
public void MultiIncWithoutLocks()
{
ThreadPool.QueueUserWorkItem(x => IncOneWithoutLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithoutLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithoutLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithoutLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithoutLock());
}
public void MultiIncWithLocks()
{
ThreadPool.QueueUserWorkItem(x => IncOneWithLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithLock());
ThreadPool.QueueUserWorkItem(x => IncOneWithLock());
}
private void IncOneWithoutLock()
{
var c = 0;
foreach (var i in CounterListOne)
{
CounterListOne[c++] = i+1;
Thread.Sleep(Next(80 * DelayFactor, 150 * DelayFactor));
}
}
private void IncOneWithLock()
{
if (CounterListOne == null)
{
Log("CounterListOne == null");
return;
}
lock (this)
{
var c = 0;
foreach (var i in CounterListOne)
{
CounterListOne[c++] = i + 1;
Thread.Sleep(Next(80 * DelayFactor, 150 * DelayFactor));
}
}
}
private void InitCounterLists()
{
InitCounterOne();
InitCounterTwo();
InitCounterThree();
}
private void InitCounterOne()
{
for (int i = 0; i < Next(1, 5); i++)
{
CounterListOne.Add(0);
}
}
private void InitCounterTwo()
{
for (int i = 0; i < Next(1, 5); i++)
{
CounterListTwo.Add(0);
}
}
private void InitCounterThree()
{
for (int i = 0; i < Next(1, 5); i++)
{
CounterListThree.Add(0);
}
}
private void StartBackgroundLogger()
{
_dT = new DispatcherTimer();
_dT.Tick += (a,b) => LogLists();
_dT.Interval = new TimeSpan(0,0,0,3);
_dT.Start();
}
}