C# Yield 是否会释放锁?

发布于 2024-10-10 05:27:01 字数 1015 浏览 5 评论 0原文

我有以下方法:

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;
    }

我刚刚添加了 lock(Database) 来尝试消除一些并发问题。不过我很好奇,yield return 会释放 Database 上的锁定,然后在下一次迭代时重新锁定吗?或者数据库会在整个迭代期间保持锁定状态吗?

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. I am curious though, will the yield return free the lock on Database and then re-lock when it goes for the next iteration? Or will Database remain locked for the entire duration of the iteration?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

活雷疯 2024-10-17 05:27:01

否,yield return 不会导致任何锁被释放/解锁。 lock 语句将扩展为 try /finally 块,并且迭代器不会将其与显式 try/finally 中的处理方式区别对待。迭代器方法。

细节有点复杂,但是 finally 块何时在迭代器方法内运行的基本规则是

  1. 当迭代器被挂起并且 Dispose 被调用时 挂起点范围内的finally 块将
  2. 在迭代器运行时运行,否则代码将触发finally 块运行。
  3. 当迭代器遇到 yieldbreak 语句时,finally 块将在 yieldbreak 处运行

No the yield return will not cause any locks to be freed / unlocked. 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.

The details are a bit more complicated but the basic rules for when a finally block will run inside an iterator method is

  1. When the iterator is suspended and Dispose is called the finally blocks in scope at the point of the suspend will run
  2. When the iterator is running and the code would otherwise trigger a finally the finally block runs.
  3. When the iterator encounters a yield break statement the finally blocks in scope at the point of the yield break will run
猥︴琐丶欲为 2024-10-17 05:27:01

锁转换为 try/finally(普通 C#)。

在迭代器块(又名yield)中,“finally”成为枚举器的IDisposable.Dispose()实现的一部分。当您使用最后一个数据时,也会在内部调用此代码。

“foreach”自动调用 Dispose(),因此如果您使用“foreach”(或常规 LINQ 等),它将会被解锁。

但是,如果调用者直接使用 GetEnumerator()(非常罕见)并且读取所有数据并且调用 Dispose(),则锁不会被释放。

我必须检查它是否有最终确定者;它可能会被GC释放,但我不会在上面打赌。

The lock translates to try/finally (normal C#).

In Iterator blocks (aka yield), "finally" becomes part of the IDisposable.Dispose() implementation of the enumerator. 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 regular LINQ etc), it will get unlocked.

However, if the caller uses GetEnumerator() directly (very rare) and doesn't read all the data and doesn't call Dispose(), then the lock will not be released.

I would have to check to see if it gets a finaliser; it might get released by GC, but I wouldn't bet money on it.

天生の放荡 2024-10-17 05:27:01

数据库对象将被锁定,直到迭代完成(或迭代器被释放)。

这可能会导致锁定时间过长,我建议不要这样做。

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.

樱桃奶球 2024-10-17 05:27:01

锁一直有效,直到超出 lock() 的范围。屈服并不能做到这一点。

The lock remains in effect until you get outside of the scope of lock(). Yielding does not do that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文