假设我有一个带有两个按钮 (button1
和button2
) 和一个资源对象 ( r
) 的表单。资源有自己的锁定和解锁代码来处理并发。资源可以被任何线程修改。
单击时button1
,它的处理程序会对其r
自身进行一些修改,然后_IndependentResourceModifierAsync()
异步调用它r
在生成的任务中进行一些修改。_IndependentResourceModifierAsync()
在执行此操作之前获取r
' 锁。也因为处理程序r
自己搞砸了,它也获得了r
' 锁。
单击时button2
,它只是_IndependentResourceModifierAsync()
直接调用。它本身没有锁定。
如您所知,按钮的处理程序将始终在主线程上执行(除了 spawned Task
)。
我想保证两件事:
- 如果在主线程锁定资源时单击
button1
或button2
单击,将引发异常。(不能使用Monitor
orMutex
因为它们是线程驱动的) button1_Click()
从through嵌套的锁_IndependentResourceModiferAsync()
不应导致死锁。(不能使用Semaphore
)。
基本上,我认为我正在寻找的是一个“基于堆栈的锁”,如果这样的事情存在或什至是可能的。因为当异步方法在等待之后继续时,它会恢复堆栈状态。我做了很多寻找其他有这个问题但没有找到的人。这可能意味着我把事情复杂化了,但我很好奇人们对此有什么看法。可能有一些非常明显的东西我错过了。非常感谢。
public class Resource
{
public bool TryLock();
public void Lock();
public void Unlock();
...
}
public class MainForm : Form
{
private Resource r;
private async void button1_Click(object sender, EventArgs e)
{
if (!r.TryLock())
throw InvalidOperationException("Resource already acquired");
try
{
//Mess with r here... then call another procedure that messes with r independently.
await _IndependentResourceModiferAsync();
}
finally
{
r.Unlock();
}
}
private async void button2_Click(object sender, EventArgs e)
{
await _IndependentResourceModifierAsync();
}
private async void _IndependentResourceModiferAsync()
{
//This procedure needs to check the lock too because he can be called independently
if (!r.TryLock())
throw InvalidOperationException("Resource already acquired");
try
{
await Task.Factory.StartNew(new Action(() => {
// Mess around with R for a long time.
}));
}
finally
{
r.Unlock();
}
}
}