[英]new thread doesn't recognize main thread already created singleton
I am unsure why my new thread doesn't recognize the singleton instance that was already created. 我不确定为什么我的新线程无法识别已经创建的单例实例。 At startup, I have a Repository class that creates a COM_Component class, which creates a DataSubscriber class.
在启动时,我有一个Repository类,它创建一个COM_Component类,它创建一个DataSubscriber类。 Here is the order of instantiation:
这是实例化的顺序:
The problem is, when DataSubscriber calls the singleton, it does not recognize it being called before and calls the constructor, which continues to loop through all the steps above repeatedly. 问题是,当DataSubscriber调用单例时,它不会识别它之前被调用并调用构造函数,后者继续循环遍历上面的所有步骤。 I thought that I had the singleton setup so that multiple threads could access the singleton correctly.
我认为我有单例设置,以便多个线程可以正确访问单例。 I realize it would be better to remove the multi-threading, but this is the way the example was setup and I'd like to get something up and running quickly.
我意识到删除多线程会更好,但这是设置示例的方式,我想快速启动并运行。
Here's how the Repository class looks: 以下是Repository类的外观:
public class Repository
{
public COM_Component component;
public String defaultProjectName = "MainDB";
public DataSet projectRepo;
public DataTable theProjects;
public DataTable theTasks;
private static Repository _instance = null;
private static readonly object _locker = new object();
private Repository()
{
InitializeRepos();
lock (_locker)
{
component = new COM_Component();
component.StartListen();
}
}
public static Repository Instance
{
get
{
if (_instance == null)
{
lock (_locker)
{
if (_instance == null)
{
_instance = new Repository();
}
}
}
return _instance;
}
}
The COM_Component creates the DataSubscriber and starts the listening thread: COM_Component创建DataSubscriber并启动监听线程:
public COM_Component()
{
}
public void StartListen()
{
dataSubscriber = new DataSubscriber(this);
//Spawn a new thread for each subscriber, condense into a single threaded subscriber in the near future
_listenThread[_numThreads] = new Thread(new ThreadStart(DataSubscriber.Listen));
_listenThread[_numThreads].Name = "DataSubscriber";
_listenThread[_numThreads].Start();
_numThreads++;
}
And then the data handler for the DataSubscriber is OnDataReceived(), operating on the new thread. 然后DataSubscriber的数据处理程序是OnDataReceived(),在新线程上运行。 It's the calls to Repository.Instance that trigger the constructor again:
这是对Repository.Instance的调用再次触发构造函数:
public void OnDataReceived(DataType msg)
{
var selectStatement = string.Format("TaskName = '{0}'", new string(msg.msgID.Value));
DataRow[] rows = Repository.Instance.theTasks.Select(selectStatement);
if (rows.Length < 1)
{
DataRow newRow = Repository.Instance.theTasks.NewRow();
Guid thisGuid = new Guid();
newRow["TaskGuid"] = thisGuid;
newRow["PlanID"] = Repository.Instance.defaultProjectName;
newRow["TaskName"] = new string(msg.msgID.Value);
Repository.Instance.theTasks.Rows.Add(newRow);
}
}
I'd appreciate tips on how to modify this code and get it working quickly, as I have already read the posts about multi-threaded dragons and that I am crunchy and good with ketchup. 我很欣赏有关如何修改此代码并使其快速运行的提示,因为我已经阅读了有关多线程龙的帖子,而且我对番茄酱很脆弱。 :)
:)
Thanks! 谢谢! Myca
Myca
I think you have a simple race condition: 我认为你有一个简单的竞争条件:
1) The first call to Repository.Instance
calls the Repository
constructor 1)对
Repository.Instance
的第一次调用调用Repository
构造函数
2) The Repository
constructor kicks off threads by way of component.StartListen()
2)
Repository
构造函数通过component.StartListen()
启动线程
3) One of those threads gets into OnDataReceived()
and calls Repository.Instance
before the constructor has returned on the original thread 3)其中一个线程进入
OnDataReceived()
并在构造函数返回原始线程之前调用Repository.Instance
4) _instance
is still null at this point since the assignment does not occur until after the constructor returns, so the code creates another instance 4)此时
_instance
仍为null,因为在构造函数返回之前不会发生赋值,因此代码会创建另一个实例
Perhaps move this instruction: 也许移动这个指令:
component.StartListen();
to the Instance
getter itself: Instance
getter本身:
if (_instance == null)
{
_instance = new Repository();
_instance.component.StartListen();
}
Note that this means someone could get _instance
before listening is done being set up if they call it at the exact right moment. 请注意,这意味着如果有人在正确的时刻调用它,则可以在设置完成之前获得
_instance
。 You'd have to decide whether that's actually possible and, if so, whether it's a problem. 你必须决定这是否真的可行,如果是的话,是否是一个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.