假设我有一个带有两个按钮 (button1和button2) 和一个资源对象 ( r) 的表单。资源有自己的锁定和解锁代码来处理并发。资源可以被任何线程修改。
单击时button1,它的处理程序会对其r自身进行一些修改,然后_IndependentResourceModifierAsync()异步调用它r在生成的任务中进行一些修改。_IndependentResourceModifierAsync()在执行此操作之前获取r' 锁。也因为处理程序r自己搞砸了,它也获得了r' 锁。
单击时button2,它只是_IndependentResourceModifierAsync()直接调用。它本身没有锁定。
如您所知,按钮的处理程序将始终在主线程上执行(除了 spawned Task)。
我想保证两件事:
- 如果在主线程锁定资源时单击
button1或button2单击,将引发异常。(不能使用MonitororMutex因为它们是线程驱动的) 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();
}
}
}