amo*_*amo 4 .net c# multithreading synchronization
我有一个场景,我的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);
}
Run Code Online (Sandbox Code Playgroud)
DoStuff()而DoOtherStuff()在不长时间运行的方法,不以其他方式共享资源.通常DoThis()并DoThat()不会同时调用.但我仍然需要防止潜在的僵局.
我怎样才能最好地实现DoThis(),DoThat()在C#中?
编辑 我的场景现在很简单,因为没有任意数量的线程调用这些函数.出于简化的目的,有一个调用程序线程以任意顺序调用这些函数.因此,不会同时调用这两个方法,而是调用者将以任何顺序逐个调用这些方法.我无法控制调用者线程的代码,所以我想强制执行连续调用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();
}
Run Code Online (Sandbox Code Playgroud)
我们可以像下面这样实现我们的定时锁存器.
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2496 次 |
| 最近记录: |