避免使用锁启动新线程

这是否可以锁定一个线程的方法并强制另一个线程走得更远,而不是等到第一个线程完成?这个问题可以通过静态线程或一些适当的模式来解决,其中一个实例是下面提到的服务。


出于演示目的,可以使用如下静态布尔值来完成。


public class SomeService

{

  private readonly IRepository _repo;

  public SomeService(IRepository repo)

  {

    _repo = repo;

  }


  private Thread threadOne;


  public static bool isLocked { get; set; }


  public void StartSomeMethod()

  {

    if(!isLocked)

    {

      threadOne = new Thread(SomeMethod);

      isLocked = true;

    }

  }


  public void SomeMethod()

  {

    while(true)

    {

      lots of time

    }

    ...

    isLocked = false;

  }

}

我想避免用户意外单击两次启动并且意外第二个线程在第一次完成后立即启动的情况。


千万里不及你
浏览 101回答 3
3回答

米脂

你可以使用锁:)object locker = new object();void MethodToLockForAThread(){    lock(locker)    {      //put method body here    }}现在的结果是,当这个方法被一个线程(任何线程)调用时,它会在锁的开头放置类似标志的东西:“停止!你不能再进一步了,你必须等待!” 就像十字路口的红灯。当首先调用此方法的线程离开作用域时,然后在作用域的开头,这个“红灯”变为绿色。如果您不想在该方法已被另一个线程调用时调用该方法,唯一的方法是使用 bool 值。例如:object locker = new object();bool canAccess = true;void MethodToLockForAThread(){    if(!canAccess)      return;    lock(locker)    {      if(!canAccess)        return;      canAccess = false;                  //put method body here      canAccess = true;    }}锁定范围内对 canAccess 的其他检查是因为评论中的内容。不,它真的是线程安全的。这是一种在线程安全单例中可见的保护。编辑在与 mjwills 讨论后,我必须改变主意,将更多内容转变为 Monitor.TryEnter。你可以这样使用它:object locker = new object();void ThreadMethod(){  if(Monitor.TryEnter(locker, TimeSpan.FromMiliseconds(1))  {     try     {       //do the thread code     }     finally     {       Monitor.Exit(locker);     }  } else    return; //means that the lock has not been aquired}现在,由于某些异常或其他线程已经获取了锁,因此无法获取锁。在第二个参数中,您可以传递线程等待获取锁的时间。我在这里给了很短的时间,因为你不希望其他线程在第一次做的时候做这项工作。所以这个解决方案似乎是最好的。当另一个线程无法获得锁时,它会走得更远而不是等待(它会等待1毫秒)。

哆啦的时光机

由于lock是围绕类的特定于语言的包装器Monitor,因此您需要Monitor.TryEnter:public class SomeService{    private readonly object lockObject = new object();    public void StartSomeMethod()    {        if (Monitor.TryEnter(lockObject))        {            // start new thread        }    }    public void SomeMethod()    {        try        {            // ...        }        finally        {            Monitor.Exit(lockObject);        }    }    }

慕的地6264312

您可以使用 aAutoResetEvent代替您的isLocked标志。AutoResetEvent autoResetEvent = new AutoResetEvent(true);public void StartSomeMethod(){    if(autoResetEvent.WaitOne(0))    {        //start thread    }}public void SomeMethod(){    try    {        //Do your work    }    finally    {        autoResetEvent.Set();    }}
打开App,查看更多内容
随时随地看视频慕课网APP