這真的非常接近真正的方法Bob posted我們擁有的是與特定數據合併的模板。下面的代碼試圖重用我們已經構建的模板。所以如果我們已經爲「達拉斯」建立了一個模板,我們可以重用它。我們看到的是「達拉斯」的模板,其中包含「紐約」模板應該具有的信息。當我們慢慢瀏覽代碼時,我們看不到它。我的想法是,可變SC低於正被另一個線程改變了之前它被放到哈希表genericTemplates所以當線程與達拉斯信息工作是準備把信息插入到genericTemplaes哈希表的線程與紐約合作已經改變了保存在sc內的數據,以反映紐約數據,但加蓋了達拉斯的「recordHash」密鑰。像Bob一樣,我對使用Lock語句並理解其真正的工作原理很陌生。C#多線程代碼問題破壞數據
我還被告知,線程範圍內的任何變量只與該線程有關。它只是全局變量或傳入的對象,我需要查看。有人能證實這一點。
private Template EnsureGenericTemplate(Detail details, Hashtable genericTemplates)
{
Template return_Object = null;
SectionContainer sc = null;
StringBuilder htmlTemplate = null;
string recordHash = string.Format("{0}_{1}_{2}", circleNumber, zipCode, topicCd);
lock (genericTemplates) {
hasTemplateDefined = genericTemplates.ContainsKey(recordHash);
{
if (!hasTemplateDefined)
{
templateData = getTemplateData();
htmlTemplate = new StringBuilder(foo1.HtmlTemplate);
HtmlParser = hp = new HtmlParser();
sc = hp.parseNew(htmlTemplate.ToString(), false);
//This method merges the html template with the template data based on <tags>
htmlTemplate = BuildTemplate(sc, htmlTemplate.ToString(), templateData);
//This method merges the html template with the template data base on %SomeVar%
hp.parseProperties<Detail>(ref htmlTemplate, details, false);
//Puts the htmlTemplate into an object that hold html and text
foo2.Html = htmlTemplate.ToString();
lock (genericTemplates)
{
if (!genericTemplates.ContainsKey(recordHash))
{
return_Object = new Template(foo2, sc);
genericTemplates.Add(recordHash, Object_For_Reuse);
}
}
}
if (htmlTemplate == null)
{
lock (genericTemplates)
{
if (genericTemplates.ContainsKey(recordHash))
return_Object = (Template)genericTemplates[recordHash];
}
}
return return_Object;
}
一個對象,它是可能改變永遠不要使用鎖。如果您想正確使用鎖,請創建一個僅用於鎖的對象。這是一個常見的錯誤。 所以對象lockMe = new Object(); - 並確保其靜態。 – Haedrian 2012-03-14 19:24:45
不確定您的示例是否包含足夠的詳細信息來發現問題。你似乎有3個鎖定語句。在第一個之後,'hasTemplateDefined'可以設置爲false,然後另一個線程可以定義模板,那麼你當前的線程將進入由if(!hasTemplateDefined)'保護的塊。我不知道這本身是否會造成問題,但守衛並不「安全」。 – Rob 2012-03-14 19:48:05