WP7的简单锁和线程池问题(C#)

WP7的简单锁和线程池问题(C#),c#,multithreading,windows-phone-7,C#,Multithreading,Windows Phone 7,有趣的是,我要测试墓碑和并发性,在我简单的设置过程中,我想见鬼,这真的值得麻烦吗。但是现在,在设置了一些愚蠢的测试类45分钟之后,我遇到了我不理解的第一个错误 似乎我需要在列表、锁和线程方面多做一些练习。 有人知道这会引发非法操作异常的原因吗(请参阅所附代码) 对于更喜欢F5体验的用户,以下是完整的解决方案(300kB) 不要打开视图,它们可能会使VS2010崩溃。您需要WP7工具,抱歉,尽管我很确定这个示例在纯C#上也能工作(不能工作) [编辑] 我更新了链接,现在它正在工作(使用旧代码)


有趣的是,我要测试墓碑和并发性,在我简单的设置过程中,我想见鬼,这真的值得麻烦吗。但是现在,在设置了一些愚蠢的测试类45分钟之后,我遇到了我不理解的第一个错误

似乎我需要在列表、锁和线程方面多做一些练习。 有人知道这会引发非法操作异常的原因吗(请参阅所附代码)

对于更喜欢F5体验的用户,以下是完整的解决方案(300kB)

不要打开视图,它们可能会使VS2010崩溃。您需要WP7工具,抱歉,尽管我很确定这个示例在纯C#上也能工作(不能工作)

[编辑] 我更新了链接,现在它正在工作(使用旧代码)
感谢评论,我发现了第一个bug

这项工作:

    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();
    }


}
公共类反类:TestBase
{
私人调度员;
公共int计数器a{get;set;}
公共observeCollection CounterListOne{get;set;}
公共列表计数器列表二{get;set;}
公共列表计数器列表三{get;set;}
专用常数int延迟因子=10;
公开反汇编()
{
CounterListOne=新的ObservableCollection();
counterlistwo=新列表();
CounterListThree=新列表();
initcounterlist();
StartBackgroundLogger();
}
公共无效日志列表()
{
锁(这个)
//锁(计数器列表二)
//锁(计数器列表三)
{
日志(“==============================================================================================”);
Log(“CounterListOne”+String.Join(“-”,CounterListOne.Select(x=>x.ToString()).ToArray());
Log(“counterlistwo”+String.Join(“-”,counterlistwo.Select(x=>x.ToString()).ToArray());
Log(“CounterListThree”+String.Join(“-”,CounterListThree.Select(x=>x.ToString()).ToArray());
日志(“==============================================================================================”);
}
}
公共无效运行测试()
{
日志(“不带锁的多重增量”);
//MultiIncWithoutLocks();
日志(“带锁的多重增量”);
多带锁();
}
public void MultiIncWithoutLocks()
{
QueueUserWorkItem(x=>IncOneWithoutLock());
QueueUserWorkItem(x=>IncOneWithoutLock());
QueueUserWorkItem(x=>IncOneWithoutLock());
QueueUserWorkItem(x=>IncOneWithoutLock());
QueueUserWorkItem(x=>IncOneWithoutLock());
}
public void MultiIncWithLocks()
{
QueueUserWorkItem(x=>IncOneWithLock());
QueueUserWorkItem(x=>IncOneWithLock());
QueueUserWorkItem(x=>IncOneWithLock());
QueueUserWorkItem(x=>IncOneWithLock());
QueueUserWorkItem(x=>IncOneWithLock());
}
私有无效IncOneWithoutLock()
{
var c=0;
foreach(CounterListOne中的var i)
{
CounterListOne[c++]=i+1;
睡眠(下一个(80*DelayFactor,150*DelayFactor));
}
}
专用无效IncOneWithLock()
{
if(CounterListOne==null)
{
日志(“CounterListOne==null”);
返回;
}
锁(这个)
{
var c=0;
foreach(CounterListOne中的var i)
{
CounterListOne[c++]=i+1;
睡眠(下一个(80*DelayFactor,150*DelayFactor));
}
}
}
私有void initcounterlist()
{
InitCounterOne();
InitCounterTwo();
initcounter三();
}
私用
{
for(inti=0;i日志列表();
_dT.间隔=新的时间跨度(0,0,0,3);
_dT.Start();
}
}

您应该提供更详细的异常描述。它与
foreach
和CounterListOne连接:您在迭代其值时将其更改,从而导致
invalidoOperationException

您正在使用可观察集合将视图与右侧绑定?
这里发生的事情是,通过更新ObservaleCollection中的值,您实际上是在试图通过非UI线程更新UI,这会导致异常。您是否使用Dispatcher.BeginInvoke来更新值,它将起作用

Dispatcher.BeginInvoke(()=>{//此代码位于UI线程上。})

不幸的是,这将排序或破坏部分测试,因为它将所有值更新活动卸载回UI。解决这个问题的一种方法是创建一个定制的
Iobservable
元素。您可以在需要时存储和更新该对象中的值,并在需要时手动调用它的
Updated
事件(通过
Dispatcher.BeginInvoke
)。这至少会将值的更新完全放在不同的线程上。但由于Silverlight可视化的安排方式,您可以