2013-06-05 67 views
0

嗨我是使用並行任務的新手。我有一個需要並行運行多次的功能。下面是虛擬代碼來表明這一點,並行任務共享一個全局變量

public MyClass GlobalValue; 

static void Main(string[] args) 
{ 
    Task task1 = Task.Factory.StartNew(() => SaveValue()); 
    Task task2 = Task.Factory.StartNew(() => SaveValue()); 
    Task task3 = Task.Factory.StartNew(() => SaveValue()); 
} 

public void SaveValue() 
{ 
    string val = GetValueFromDB(); 
    if (GlobalValue == NULL) 
    { 
     GlobalValue = New MyClass(val); 
    } 
    else if (GlobalValue.Key != val) 
    { 
     GlobalValue = New MyClass(val); 
    } 

    string result = GlobalValue.GetData(); 
} 

現在行GlobalValue = New GlobalValue(val)每次被調用。請幫助我。我認爲全局變量存在問題。

+1

我覺得你有與比賽條件和缺乏任何一種鎖在這裏的一個問題.... –

+0

這是什麼代碼的意義呢? – Rotem

+1

您需要編寫線程安全的代碼。祝你好運。 – SLaks

回答

1

好,爲什麼不這樣做

static void Main() 
{ 
    var tasks = new[] 
     { 
      Task.Factory.StartNew(() => YourFunction()), 
      Task.Factory.StartNew(() => YourFunction()), 
      Task.Factory.StartNew(() => YourFunction()) 
     }; 

    Task.WaitAll(tasks) 
} 

public static string YourFunction() 
{ 
    var yourClass = new MyClass(GetValueFromDB()); 
    return yourClass.GetData(); 
} 

我不明白爲什麼你需要GlobalValue。實例化MyClass昂貴嗎?更值得注意的是,你不會對結果做任何事情,所以一切都是沒有意義的。


由於功能都可用,假設你使用.NET 4.5(C#5.0),你可以做

static void Main() 
{ 
    await Task.WhenAll(YourFunction(), YourFunction(), YourFunction()); 
} 

public async Task<string> YourFunction() 
{ 
    return new MyClass(GetValueFromDB()).GetData(); 
} 

爲了說明起見,你還是可以使用全球變量,但它會大量減少並行化的好處。你只需要確保你序列化訪問共享狀態或使用線程安全類型爲你做。

改編自你的榜樣

public void SaveValue() 
{ 
    string val = GetValueFromDB(); 
    MyClass thisValue; 
    lock (this.GlobalValue) 
    { 
     if (this.GlobalValue == NULL) 
     { 
      this.GlobalValue = new MyClass(val); 
     } 
     else if (this.GlobalValue.Key != val) 
     { 
      this.GlobalValue = new MyClass(val); 
     } 

     thisValue = this.GlobalValue 
    } 

    string result = thisValue.GetData(); 
} 
2

您需要同步對共享數據的訪問,因爲每個線程都會嘗試同時訪問它,並且看到它爲空,那麼將分配所有數據。

請注意,如果通過鎖定完成同步,可能會導致三個線程有效地按順序運行,因爲一次只能有一個線程進入鎖定。