锁语句中收益回报 [英] yield returns within lock statement

查看:91
本文介绍了锁语句中收益回报的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个锁语句收益回报率并锁定得到取出每个收益率(5次在下面的例子),或者只有一次在列表中的所有项目?



感谢

 私人列表<串GT; _data =新列表与所述;串GT;(){1,2,3,4,5}; 
私有对象_locker =新的对象();
公开的IEnumerable<串GT;的GetData()
{
锁(_locker)
{
的foreach(在_data字符串s)
{
收益率的回报秒;
}
}
}


解决方案

修改这个答案是错的。请参阅下面的@ Lockszmith的回答。



意译:



该锁的从不每间发行yeald返回。
注:当枚举完成它不过释放,即当foreach循环结束



结束修改



原来的答复(错误):



在你的情况下,锁将只服用一次。因此,在短,只有一次。但是,你不处理任何共享的资源。当你开始处理像下面的控制台应用程序,一些有趣的事情发生的共享资源。



您会从结果中看到,锁被暂时每个产量释放。此外,请注意在表1中的锁不被释放,直到所有的项目已被写入到控制台,表明getData()方法与循环的每次迭代,并且锁定部分执行必须与每个暂时释放yield语句。

 静态无效的主要(字串[] args)
{
对象更衣室=新对象();
IEnumerable的<串GT; myList1 =新DataGetter()的GetData(储物柜,列表1)。
IEnumerable的<串GT; myList2 =新DataGetter()的GetData(储物柜,列表2)。
Console.WriteLine(开始GETDATA);
的foreach(在myList1变种X)
{
Console.WriteLine(列表1 {0},X);
的foreach(在myList2变种Y)
{
Console.WriteLine(列表2 {0},Y);
}
}
Console.WriteLine(结束的GetData);
到Console.ReadLine();
}

公共类DataGetter
{
私有列表<串GT; _data =新列表与所述;串GT;(){1,2,3,4,5};

公开的IEnumerable<串GT;的GetData(对象lockObj,串LISTNAME)
{
Console.WriteLine({0}做起,LISTNAME);
锁(lockObj)
{
Console.WriteLine({0}锁定拍摄LISTNAME);
的foreach(字符串s在_data)
{
收益率的回报秒;
}
}
Console.WriteLine({0}锁定解除,LISTNAME);
}
}
}



结果:



 启动GETDATA 
表1启动
表1锁定拍摄
表1
名单2启动
表2锁定拍摄
表2 1
名单2
表2 3
表2 4
表2 5
名单2锁定解除
表1 2
表2开始
表2锁定拍摄
表2 1
名单2
表2 3
名单2 4
表2 5
表2锁定释放
表1 3
表2开始
表2锁定拍摄
表2 1
表2
表2 3
表2 4
表2 5
表2锁定释放
表1 4
表2开始
表2锁定拍摄
表2 1
名单2
表2 3
表2 4
表2 5
表2锁定释放
文件清单1 5
表2开始
表2锁定拍摄
表2 1
名单2
表2 3
表2 4
文件清单2 5
表2锁定释放
表1锁定释放
端的GetData

不过,在这里,他真的很酷的事情是结果。注意,行开始的GetData调用DataGetter()。的GetData()之后,但在getData()方法内发生的一切之前发生。这就是所谓的延迟执行,这表明了yield return语句的美感和实用性:任何你外环内就可以跳出循环,不会有更多的呼叫内环。这意味着,你不必遍历整个内部循环,如果你没有,这也意味着你将开始得到的结果你刚才的外环。


if i have a yield return in a lock statement does the lock get taken out on each yield (5 times in the example below) or only once for all the items in the list?

Thanks

    private List<string> _data = new List<string>(){"1","2","3","4","5"};
    private object _locker =new object();
    public IEnumerable<string> GetData()
    {
        lock (_locker)
        {
            foreach (string s in _data)
            {
                yield return s;
            }
        }
    }

解决方案

Edit: This answer was wrong. Please see @Lockszmith's answer below.

Paraphrased:

The lock is NEVER released between each yeald return. NOTE: It is however released when the enumerator is done, i.e. when the foreach loop ends.

End Edit

Original Answer (wrong):

In your scenario, the lock will only be taken once. So in short, only once. However, you are not dealing with any shared resources. When you start to deal with shared resources like in the console app below, some interesting things happen.

You will see from the results that the lock is temporarily released on each yield. Also, note that the lock on List 1 is not released until all of the items have been written to the console, demonstrating that the GetData() method is executed partially with each iteration of the loop and that the lock must be released temporarily with each yield statement.

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

Results:

            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

However, he really cool thing here is the results. Note that the line, "start GetData" occurs after the call to DataGetter().GetData() but before everything that occurs within the GetData() method. This is called deferred execution and it demonstrates the beauty and usefulness of the yield return statement: Anywhere within your outer loop you can break out of the loop and there will be no more calls to the inner loop. This means that you don't have to iterate the entire inner loop if you don't have to and it also means that you will start to get results to your outer loop earlier.

这篇关于锁语句中收益回报的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆