[英]Does the C# Yield free a lock?
I have the following method: 我有以下方法:
public static IEnumerable<Dictionary<string, object>> GetRowsIter
(this SqlCeResultSet resultSet)
{
// Make sure we don't multi thread the database.
lock (Database)
{
if (resultSet.HasRows)
{
resultSet.Read();
do
{
var resultList = new Dictionary<string, object>();
for (int i = 0; i < resultSet.FieldCount; i++)
{
var value = resultSet.GetValue(i);
resultList.Add(resultSet.GetName(i), value == DBNull.Value
? null : value);
}
yield return resultList;
} while (resultSet.Read());
}
yield break;
}
I just added the lock(Database)
to try and get rid of some concurancy issues. 我刚刚添加了
lock(Database)
来尝试摆脱一些尴尬的问题。 I am curious though, will the yield return
free the lock on Database
and then re-lock when it goes for the next iteration? 我很好奇,
yield return
是否会释放Database
上的锁定,然后在下一次迭代时重新锁定? Or will Database
remain locked for the entire duration of the iteration? 或者
Database
会在整个迭代期间保持锁定状态吗?
No the yield return
will not cause any locks to be freed / unlocked. yield return
不会导致任何锁定被释放/解锁。 The lock
statement will expand out to a try / finally
block and the iterator will not treat this any differently than an explicit try / finally
in the iterator method. lock
语句将扩展为try / finally
块,并且迭代器不会对迭代器方法中的显式try / finally
进行任何不同的处理。
The details are a bit more complicated but the basic rules for when a finally
block will run inside an iterator method is 细节有点复杂,但
finally
块在迭代器方法中运行的基本规则是
Dispose
is called the finally
blocks in scope at the point of the suspend will run Dispose
时,将在暂停点的范围内运行finally
块 finally
the finally
block runs. finally
触发finally
块时运行。 yield break
statement the finally
blocks in scope at the point of the yield break
will run yield break
语句时, yield break
run的点范围内的finally
块将会运行 The lock translates to try/finally (normal c#) 锁转换为try / finally(正常c#)
In Iterator blocks (aka yield), "finally" becomes part of the IDisposable.Dispose() implementation of the enumerator . 在Iterator块(又名yield)中,“finally”成为枚举器的IDisposable.Dispose()实现的一部分。 This code is also invoked internally when you consume the last of the data.
使用最后一个数据时,也会在内部调用此代码。
"foreach" automatically calls Dispose(), so if you consume with "foreach" (or regualar LINQ etc) it will get unlocked. “foreach”会自动调用Dispose(),所以如果你使用“foreach”(或regualar LINQ等), 它将被解锁。
However, if the caller uses GetEnumerator() directly (very rare) and doesnt read all the data and doesn't call Dispose() then the lock will not be released. 但是,如果调用者直接使用GetEnumerator()(非常罕见)并且不读取所有数据并且不调用Dispose(),则不会释放锁定。
I would have to check to see if or gets a finaliser; 我必须检查是否或获得终结者; it might get released by GC, but I wouldn't bet money on it.
它可能会被GC释放,但我不会赌钱。
The Database object will be locked until iteration finishes (or the iterator is disposed). 数据库对象将被锁定,直到迭代完成(或处理迭代器)。
This might lead to excessive periods of locking, and I would recommend against doing it like this. 这可能导致过多的锁定时间,我建议不要这样做。
The lock remains in effect until you get outside of the scope of lock(). 锁定保持有效,直到您超出lock()的范围。 Yielding does not do that.
让步不会那样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.