[英]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.