使用Dispatcher Timer在WPF中进行线程锁定

时间:2017-12-27 13:24:12

标签: c# wpf multithreading

我有一个WPF C#应用程序,它使用Dispatcher Timers来更新UI。

在主题A中,在类DataProcessor中,我正在更新一个变量,一个名为' FinalMarkers'的自定义结构。

我使用以下方法锁定变量更新:

 static readonly Object mLock = new Object();
            static List<Storage.FiducialMarkers> finalMarkers;
            public List<Storage.FiducialMarkers> FinalMarkers
                {
                    get { return finalMarkers; }
                    set
                    {
                        lock (mLock)
                        {
                            finalMarkers = value;
                        }
                    }
                }

然后在线程内运行:

FinalMarkers = pullFiducialData();

在我的UI表单中,我将DataProcessor的实例传递给Form的构造函数。

        protected DataProcessor Data = null;

 public FormView(DataProcessor _Data)
        {
                       Data = _Data;
          }

然后我有一个调度变量的调度程序计时器:

 DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(20);
            timer.Tick += timer_Tick3d;
            timer.Start();

在计时器滴答功能中,我抓住了值:

        List<Storage.FiducialMarkers> tmpList = new List<Storage.FiducialMarkers>();

 tmpList = Data._processingArgs.FinalMarkers;

这会运行一段时间,然后崩溃而不会出错。我处理线程锁错了吗?

这是将数据从另一个线程传递到调度程序计时器的正确方法吗?

谢谢。

1 个答案:

答案 0 :(得分:1)

您需要锁定get以及set

public List<Storage.FiducialMarkers> FinalMarkers
    {
        get {
            lock (mLock) {
                return finalMarkers;
            }
        }
        set
        {
            lock (mLock)
            {
                finalMarkers = value;
            }
        }
    }

如果您在拨打set时接听锁定,那么您可以保护自己免受同时运行的两个安装人员的攻击,但如果您在拨打get时没有取锁,那么该集合可能会在未经协调的读者读取时篡改该值;无论作者是否持有锁,都会发生这种情况。锁是多个线程之间的协议。如果只有一个线程(编写器)绑定到协议,那么另一个线程(读取器)将在不合时宜的时刻执行其读取,并可能导致某种冲突或损坏。

锁定说“让我们不要同时执行这段代码”。您必须通过在锁定块中访问finalMarkers所涉及的任何代码来获得所有线程的同意。

FYI:结构本身具有值语义,因此在执行get时会复制它。