新线程无法识别已创建的单例主线程



我不确定为什么我的新线程无法识别已经创建的单例实例。 在启动时,我有一个创建COM_Component类的存储库类,该类创建一个 DataSubscriber 类。 以下是实例化的顺序:

  1. 创建单一实例存储库类。
  2. 存储库类创建COM_Component类。
  3. COM_Component类创建 DataSubscriber 类。
  4. COM_Component方法生成新线程,以便 DataSubscriber 侦听传入的数据。
  5. 新线程上的 DataSubscriber 接收数据并使用 Repository.Instance(( 来存储数据。

问题是,当 DataSubscriber 调用单例时,它无法识别之前被调用并调用构造函数,构造函数继续重复遍历上述所有步骤。 我以为我有单例设置,以便多个线程可以正确访问单例。 我意识到最好删除多线程,但这是示例的设置方式,我想快速启动并运行一些东西。

存储库类的外观如下:

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;
        }
    }

COM_Component创建数据订阅者并启动侦听线程:

   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++;
   }

然后 DataSubscriber 的数据处理程序是 OnDataReceived((,在新线程上运行。 对 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);
        }
    }

我将不胜感激有关如何修改此代码并使其快速工作的提示,因为我已经阅读了有关多线程龙的帖子,并且我很脆,擅长番茄酱。 :)

谢谢!米卡

我认为你有一个简单的竞争条件:

1( 第一次调用 Repository.Instance 调用 Repository 构造函数

2( Repository构造函数通过component.StartListen()启动线程

3( 其中一个线程进入OnDataReceived()并在构造函数返回原始线程之前调用Repository.Instance

4( 此时_instance仍然是 null,因为赋值直到构造函数返回后才会发生,因此代码会创建另一个实例

也许移动此指令:

component.StartListen();

对于Instance吸气者本身:

if (_instance == null)
{
   _instance = new Repository();
   _instance.component.StartListen();
}

请注意,这意味着如果某人在正确的时刻调用它,则可以在设置收听完成之前获得_instance。你必须决定这是否真的可能,如果是的话,这是否是一个问题。

最新更新