編集: この回答は間違っていましたが、正しいとマークされているため削除できません。正解については、以下の @Lockszmith の回答を参照してください。
言い換え:
yieldが返されるたびにロックが解除されることはありません。注: ただし、列挙子が完了すると、つまり foreach ループが終了すると解放されます。
編集を終了
元の回答 (間違っています):
あなたのシナリオでは、ロックは一度だけ取得されます。つまり、一度だけです。ただし、共有リソースは扱っていません。以下のコンソール アプリのように共有リソースを処理し始めると、いくつかの興味深いことが起こります。
結果から、各 yield でロックが一時的に解放されることがわかります。また、リスト 1 のロックは、すべての項目がコンソールに書き込まれるまで解放されないことに注意してください。これは、GetData() メソッドがループの反復ごとに部分的に実行され、ループの反復ごとにロックを一時的に解放する必要があることを示しています。利回り宣言。
static void Main(string[] args)
{
object locker = new object();
IEnumerable<string> myList1 = new DataGetter().GetData(locker, "List 1");
IEnumerable<string> myList2 = new DataGetter().GetData(locker, "List 2");
Console.WriteLine("start Getdata");
foreach (var x in myList1)
{
Console.WriteLine("List 1 {0}", x);
foreach(var y in myList2)
{
Console.WriteLine("List 2 {0}", y);
}
}
Console.WriteLine("end GetData");
Console.ReadLine();
}
public class DataGetter
{
private List<string> _data = new List<string>() { "1", "2", "3", "4", "5" };
public IEnumerable<string> GetData(object lockObj, string listName)
{
Console.WriteLine("{0} Starts", listName);
lock (lockObj)
{
Console.WriteLine("{0} Lock Taken", listName);
foreach (string s in _data)
{
yield return s;
}
}
Console.WriteLine("{0} Lock Released", listName);
}
}
}
結果:
start Getdata
List 1 Starts
List 1 Lock Taken
List 1 1
List 2 Starts
List 2 Lock Taken
List 2 1
List 2 2
List 2 3
List 2 4
List 2 5
List 2 Lock Released
List 1 2
List 2 Starts
List 2 Lock Taken
List 2 1
List 2 2
List 2 3
List 2 4
List 2 5
List 2 Lock Released
List 1 3
List 2 Starts
List 2 Lock Taken
List 2 1
List 2 2
List 2 3
List 2 4
List 2 5
List 2 Lock Released
List 1 4
List 2 Starts
List 2 Lock Taken
List 2 1
List 2 2
List 2 3
List 2 4
List 2 5
List 2 Lock Released
List 1 5
List 2 Starts
List 2 Lock Taken
List 2 1
List 2 2
List 2 3
List 2 4
List 2 5
List 2 Lock Released
List 1 Lock Released
end GetData
しかし、ここで彼が本当に素晴らしいのは結果です。「start GetData」という行は、DataGetter().GetData() の呼び出しの後、GetData() メソッド内で発生するすべての前に発生することに注意してください。これは遅延実行と呼ばれ、yield return ステートメントの美しさと有用性を示しています。外側のループ内のどこでもループから抜け出すことができ、内側のループへの呼び出しはもうありません。これは、必要がなければ内側のループ全体を反復する必要がないことを意味し、外側のループに早く結果を取得し始めることも意味します。