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