为了账号安全,请及时绑定邮箱和手机立即绑定

避免使用锁启动新线程

避免使用锁启动新线程

C#
千万里不及你 2022-06-18 17:32:17
这是否可以锁定一个线程的方法并强制另一个线程走得更远,而不是等到第一个线程完成?这个问题可以通过静态线程或一些适当的模式来解决,其中一个实例是下面提到的服务。出于演示目的,可以使用如下静态布尔值来完成。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;  }}我想避免用户意外单击两次启动并且意外第二个线程在第一次完成后立即启动的情况。
查看完整描述

3 回答

?
米脂

TA贡献1836条经验 获得超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毫秒)。


查看完整回答
反对 回复 2022-06-18
?
哆啦的时光机

TA贡献1779条经验 获得超6个赞

由于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);

        }

    }    

}


查看完整回答
反对 回复 2022-06-18
?
慕的地6264312

TA贡献1817条经验 获得超6个赞

您可以使用 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();

    }

}


查看完整回答
反对 回复 2022-06-18
  • 3 回答
  • 0 关注
  • 100 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信