首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单锁和ThreadPoolQuestion for WP7 (C#)

简单锁和ThreadPoolQuestion for WP7 (C#)
EN

Stack Overflow用户
提问于 2011-03-02 09:45:23
回答 2查看 507关注 0票数 1

有趣的是,我要测试墓碑化和并发性,在我简单的设置过程中,我想这是多么值得一试。但是现在,在设置了一些愚蠢的测试课程45分钟后,我遇到了我不明白的第一个错误。

似乎我需要在列表、锁和线程中多练习一些。有人知道为什么会引发非法操作异常(请参阅附加代码)。

对于一个更喜欢F5体验的人来说,以下是完整的解决方案(300 is )

http://www.filesavr.com/TXXXFVE40GTJK43

不要打开视图,它们可能会破坏您的VS2010。您需要WP7工具,很抱歉,尽管我非常肯定这个示例在纯C#上也能工作(而不是起作用)。

编辑I更新链接,现在它正在工作(用旧代码)

我发现了第一个bug,多亏了这条评论。

这样做是可行的:

代码语言:javascript
复制
    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

为了您的方便,期望发生在这个函数中,它是一个无效的操作期望:

代码语言:javascript
复制
 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));
            }
        }
    }

下面是测试类的完整来源:

代码语言:javascript
复制
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();
    }


}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-02 10:09:24

您应该提供更详细的异常描述。它与foreach和CounterListOne相关联:在迭代其值时对其进行更改,从而导致InvalidOperationException

票数 3
EN

Stack Overflow用户

发布于 2011-03-02 10:27:38

您正在使用可观察的集合来绑定您的视图对对吗?

这里发生的事情是,通过更新观测结果中的值,您必须尝试通过非UI线程更新UI,这将导致您的异常。是使用Dispatcher.BeginInvoke更新值,而不是使用它。

Dispatcher.BeginInvoke( () => { // This code is on the UI thread. });

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5165706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档