![](/img/trans.png)
[英]How to update a DataTable created on Main Thread by a new thread in C#?
[英]new thread doesn't recognize main thread already created singleton
我不确定为什么我的新线程无法识别已经创建的单例实例。 在启动时,我有一个Repository类,它创建一个COM_Component类,它创建一个DataSubscriber类。 这是实例化的顺序:
问题是,当DataSubscriber调用单例时,它不会识别它之前被调用并调用构造函数,后者继续循环遍历上面的所有步骤。 我认为我有单例设置,以便多个线程可以正确访问单例。 我意识到删除多线程会更好,但这是设置示例的方式,我想快速启动并运行。
以下是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;
}
}
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++;
}
然后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);
}
}
我很欣赏有关如何修改此代码并使其快速运行的提示,因为我已经阅读了有关多线程龙的帖子,而且我对番茄酱很脆弱。 :)
谢谢! Myca
我认为你有一个简单的竞争条件:
1)对Repository.Instance
的第一次调用调用Repository
构造函数
2) Repository
构造函数通过component.StartListen()
启动线程
3)其中一个线程进入OnDataReceived()
并在构造函数返回原始线程之前调用Repository.Instance
4)此时_instance
仍为null,因为在构造函数返回之前不会发生赋值,因此代码会创建另一个实例
也许移动这个指令:
component.StartListen();
Instance
getter本身:
if (_instance == null)
{
_instance = new Repository();
_instance.component.StartListen();
}
请注意,这意味着如果有人在正确的时刻调用它,则可以在设置完成之前获得_instance
。 你必须决定这是否真的可行,如果是的话,是否是一个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.