gpt4 book ai didi

c# - 如何在C#中实现与定时器的同步

转载 作者:太空狗 更新时间:2023-10-30 00:56:31 24 4
gpt4 key购买 nike

我的 C# 类有两个方法 DoThis()DoThat()外部调用者。这两个方法需要通过以下方式同步:

  • 调用 DoThis() 后,至少等待 t1 秒,然后再继续执行 DoThat()
  • 调用 DoThat() 后,至少等待 t2 秒,然后再继续执行 DoThis()

所以本质上是伪代码:

static SomeCustomTimer Ta, Tb;
static TimeSpan t1, t2;

public static void DoThis()
{
if(Tb.IsRunning())
Tb.WaitForExpiry();

DoStuff();
Ta.Start(t1);
}

public static void DoThat()
{
if(Ta.IsRunning())
Ta.WaitForExpiry();

DoOtherStuff();
Tb.Start(t2);
}

DoStuff()DoOtherStuff()长时间运行的方法,否则不共享资源。通常不会同时调用 DoThis()DoThat()。但我仍然需要防止潜在的死锁。

如何在 C# 中最好地实现 DoThis()DoThat()

编辑我现在的场景很简单,因为没有任意数量的线程调用这些函数。为了简化,有一个调用者线程以任意顺序调用这些函数。所以这两个方法不会被同时调用,而是调用者会以任意顺序一个接一个地调用这些方法。我无法控制调用者线程的代码,因此我想强制执行对 DoThis()、DoThat() 的连续调用之间的延迟。

最佳答案

这很容易用定时闩锁来解决。闩锁是打开或关闭的同步机制。当开放线程被允许通过时。当关闭的线程无法通过时。定时锁存器是一种在经过一定时间后会自动重新打开或重新关闭的锁存器。在这种情况下,我们需要一个“常开”闩锁,以便行为偏向于保持打开状态。这意味着闩锁将在超时后自动重新打开,但只有在显式调用 Close 时才会关闭。多次调用 Close 将重置计时器。

static NormallyOpenTimedLatch LatchThis = new NormallyOpenTimedLatch(t2);
static NormallyOpenTimedLatch LatchThat = new NormallyOpenTimedLatch(t1);

static void DoThis()
{
LatchThis.Wait(); // Wait for it open.

DoThisStuff();

LatchThat.Close();
}

static void DoThat()
{
LatchThat.Wait(); // Wait for it open.

DoThatStuff();

LatchThis.Close();
}

我们可以像下面这样实现我们的定时闩锁。

public class NormallyOpenTimedLatch
{
private TimeSpan m_Timeout;
private bool m_Open = true;
private object m_LockObject = new object();
private DateTime m_TimeOfLastClose = DateTime.MinValue;

public NormallyOpenTimedLatch(TimeSpan timeout)
{
m_Timeout = timeout;
}

public void Wait()
{
lock (m_LockObject)
{
while (!m_Open)
{
Monitor.Wait(m_LockObject);
}
}
}

public void Open()
{
lock (m_LockObject)
{
m_Open = true;
Monitor.PulseAll(m_LockObject);
}
}

public void Close()
{
lock (m_LockObject)
{
m_TimeOfLastClose = DateTime.UtcNow;
if (m_Open)
{
new Timer(OnTimerCallback, null, (long)m_Timeout.TotalMilliseconds, Timeout.Infinite);
}
m_Open = false;
}
}

private void OnTimerCallback(object state)
{
lock (m_LockObject)
{
TimeSpan span = DateTime.UtcNow - m_TimeOfLastClose;
if (span > m_Timeout)
{
Open();
}
else
{
TimeSpan interval = m_Timeout - span;
new Timer(OnTimerCallback, null, (long)interval.TotalMilliseconds, Timeout.Infinite);
}
}
}

}

关于c# - 如何在C#中实现与定时器的同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7524513/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com