我有一个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;
这会运行一段时间,然后崩溃而不会出错。我处理线程锁错了吗?
这是将数据从另一个线程传递到调度程序计时器的正确方法吗?
谢谢。
答案 0 :(得分:1)
您需要锁定get
以及set
。
public List<Storage.FiducialMarkers> FinalMarkers
{
get {
lock (mLock) {
return finalMarkers;
}
}
set
{
lock (mLock)
{
finalMarkers = value;
}
}
}
如果您在拨打set
时接听锁定,那么您可以保护自己免受同时运行的两个安装人员的攻击,但如果您在拨打get
时没有取锁,那么该集合可能会在未经协调的读者读取时篡改该值;无论作者是否持有锁,都会发生这种情况。锁是多个线程之间的协议。如果只有一个线程(编写器)绑定到协议,那么另一个线程(读取器)将在不合时宜的时刻执行其读取,并可能导致某种冲突或损坏。
锁定说“让我们不要同时执行这段代码”。您必须通过在锁定块中访问finalMarkers
所涉及的任何代码来获得所有线程的同意。
FYI:结构本身具有值语义,因此在执行get时会复制它。