2014-11-06 56 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