2 つのボタン (button1
とbutton2
) とリソース オブジェクト ( r
) を持つフォームがあるとします。リソースには、同時実行性を処理するための独自のロックおよびロック解除コードがあります。リソースは、任意のスレッドによって変更される可能性があります。
がbutton1
クリックされると、そのハンドラーはそれ自体を何らかの変更を加えてから、生成されたタスクで何らかの変更を行う非同期r
呼び出しを行います。これを行う前に のロックを取得します。また、ハンドラーが自分自身をいじっているため、のロックも取得します。_IndependentResourceModifierAsync()
r
_IndependentResourceModifierAsync()
r
r
r
をクリックすると、直接button2
呼び出すだけです。_IndependentResourceModifierAsync()
それ自体はロックしません。
ご存知のように、ボタンのハンドラーは常にメイン スレッドで実行されます ( spawned を除くTask
)。
保証したいことが2つあります。
- リソースがメイン スレッドによってロックされているときに または をクリックすると、例外がスローされます
button1
。button2
(Monitor
orMutex
はスレッド駆動であるため使用できません) - からのロックのネストによって
button1_Click()
デッド_IndependentResourceModiferAsync()
ロックが発生することはありません。(使用できませんSemaphore
)。
基本的に、私が探しているのは「スタックベースのロック」であり、そのようなものが存在するか、可能でさえあると思います。非同期メソッドが await 後に続行すると、スタック状態が復元されるためです。私は、この問題を抱えていたが乾いてしまった他の人をたくさん探しました. それはおそらく私が物事を複雑にしすぎていることを意味しますが、人々がそれについて何を言わなければならないのか興味があります. 私が見逃している本当に明白な何かがあるかもしれません。どうもありがとう。
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();
}
}
}