【问题标题】:C# Set Variable in ThreadC#在线程中设置变量
【发布时间】:2014-11-06 16:55:12
【问题描述】:

我正在尝试为一个私人项目使用 Threads,我有一个问题,因为我认为这很容易回答。

是否可以在另一个线程中设置变量?

这是一个小代码示例,向您展示我正在尝试做的事情:

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”的好方法。

这是可能的还是有更好的解决方案? 感谢您的想法。

(我没有测试代码 - 只是把它写出来)

【问题讨论】:

  • 你的主线程正在等待第二个线程停止,并且第二个线程不会停止,直到主线程告诉它。它会以这种速度永远持续下去。

标签: c# .net multithreading network-programming threadpool


【解决方案1】:

您调用 stop 方法的方式与调用 start 方法的方式相同:

party.StopParty();

为了确保不只是缓存在另一个线程中所做的更改,partytime 字段也应标记为volatile

【讨论】:

  • 喜欢这个? 'volatile bool 派对时间 = true;'不知道我可以在其他线程中调用方法o.O :D
  • @greece57 线程不拥有方法、对象或内存(好吧,从技术上讲,存在线程特定的内存,但您需要不遗余力地创建它)。该方法不属于任何一个线程,不同的线程只是在访问全局可访问的方法或内存。
【解决方案2】:

您应该使用同步工具,例如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();
    }
}

它是线程安全的,不仅适用于此,还适用于更高级的场景,以及处理任务。

【讨论】:

  • 我可以将此令牌也用于多个线程并通过设置一个令牌将它们全部取消吗?感谢您的回复!
  • 是的,只需将相同的令牌(实际上是副本,因为它是结构)传递到您希望取消的每个线程。更多here.
【解决方案3】:

如果希望更多线程请求同一个变量,请注意线程同步问题(当两个线程尝试访问同一个变量时)。

我将展示最安全的方式(可能超出您的需要)。最好的方法是声明一个静态对象来设置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 关键字将保证您使用正确的方式。

【讨论】:

  • 锁用于同步访问公共资源,而不是用于线程间信号。如果您想使用“保守”API,请使用 ManualResetEvent 或其 *Slim 版本。
猜你喜欢
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-25
相关资源
最近更新 更多