2014-11-06 52 views
1

我正在嘗試使用線程來進行私人項目,我有一個問題,因爲我覺得很容易回答。線程中的C#集合變量

是否可以在另一個線程中設置變量?

這裏一點點的代碼示例告訴你什麼是我想要做的事:

public class PartyClass 
{ 
    public boolean partytime = true; 

    public void MakeParty() 
    { 
      while(partytime) 
       Console.WriteLine("I'm making a party here"); 

      Console.WriteLine("The party ended. Please leave now"); 
    } 

    public void StopParty() 
    { 
      partytime = false; 
    } 
} 

public class MainThread 
{ 
    public static int Main(String[] args) 
    { 
      PartyClass party = new PartyClass(); 
      Thread partyThread = new Thread(new ThreadStart(party.MakeParty())); 
      partyThread.Start(); 
      while (!partyThread.IsAlive) ; 

      System.Threading.Thread.Sleep(5000); 

      // Now I want to somehow call the StopParty() Method 
    } 
} 

我不知道這是否是真的愚蠢的我想要做的,但我認爲這是一個很好的方式,以乾淨的方式停止「Partythread」。

這是可能的還是有更好的解決方案呢? 感謝您的想法。

(我沒有測試的代碼 - 只是寫出來我的頭)

+1

您的主線程正在等待第二個線程停止,並且第二個線程不會停止,直到主線程告訴它爲止。它會一直持續下去。 – Servy 2014-11-06 16:56:44

回答

1

調用stop方法只是你調用start方法方式:

party.StopParty(); 

爲了保證在另一個線程中所做的更改不僅被緩存,還應將partytime字段標記爲volatile

+0

是否這樣? 'volatile bool partytime = true;' 不知道我可以調用其他線程的方法oO:D – greece57 2014-11-06 21:34:32

+0

@ greece57線程不擁有方法,對象或內存(從技術上講,線程特定的內存,但你需要走出你的方式來創建它)。該方法不屬於任何一個線程,不同的線程只是簡單地訪問全局可訪問的方法或內存。 – Servy 2014-11-06 21:36:25

1

您應該使用同步功能,例如CancellationToken

你的代碼如下:

public class PartyClass 
{ 
    private readonly CancellationToken _cancellationToken; 

    public PartyClass(CancellationToken cancellationToken) 
    { 
     _cancellationToken = cancellationToken; 
    } 

    public void MakeParty() 
    { 
     while (!_cancellationToken.IsCancellationRequested) 
      Console.WriteLine("I'm making a party here"); 

     Console.WriteLine("The party ended. Please leave now"); 
    } 
} 

public class MainThread 
{ 
    public static int Main(String[] args) 
    { 
     var cancellationSource = new CancellationTokenSource(); 
     PartyClass party = new PartyClass(cancellationSource.Token); 
     Thread partyThread = new Thread(party.MakeParty); 
     partyThread.Start(); 

     System.Threading.Thread.Sleep(5000); 

     cancellationSource.Cancel(); 

     partyThread.Join(); 
    } 
} 

它是線程安全的,不僅適用於這一點,但也爲更高級的方案,以及爲使用任務。

+0

我可以使用這個令牌也用於多個線程並通過設置一個令牌來取消它們嗎? 感謝您的迴應! – greece57 2014-11-06 21:31:43

+0

是的,只是將相同的標記(實際上是它的結構副本)路徑到您希望取消的每個線程。更多[這裏](http://msdn.microsoft.com/en-us/library/dd997364(v = vs.110).aspx)。 – galenus 2014-11-06 23:45:27

0

如果想要更多線程來請求相同的變量,請注意線程同步問題(當兩個線程嘗試訪問相同的變量時)。

我將展示最安全的方式(可能超過您的需要)。最好的辦法是聲明一個靜態對象來設置一個lock以確保你有一個線程一次更改派對標誌。

public class PartyClass 
{ 

    private object _partyTimeLock = new Object(); // executed at class init 
    private boolean partyTime= true; 

    public bool IsPartyGoingOn() 
    { 
     bool itIsGoingOn = false; 
     lock(_partyTimeLock) { 
      itIsGoingOn = partyTime; 
     } 
     return itIsGoingOn; 
    } 

    public void StopParty() 
    { 
     lock(_partyTimeLock) { 
      partyTime = false; 
     } 
    } 

    public void MakeParty() 
    { 
     while(IsPartyGoingOn()) { 
       Console.WriteLine("I'm making a party here"); 
     } 

     Console.WriteLine("The party ended. Please leave now"); 
    } 
} 

在這裏這個例子中,無論是誰試圖調用IsPartyGoingOn(),你將永遠不會有一個問題(無論它的類自己的線程或另一個)。 lock關鍵字將保證您正確地完成任務。

+0

鎖定用於同步訪問公共**資源**,而不是線程間信號。如果您想使用「保守」API,請使用ManualResetEvent或其Slim版本。 – galenus 2014-11-06 18:52:46