C#整数在回调中作为引用传递?

时间:2016-10-27 04:24:09

标签: c# callback int pass-by-reference pass-by-value

我在回调和for循环方面遇到了一些问题, 说我有这个代码

public void DoSth(Action<QueryTextureResult> result, IEnumerable<string> arr)
{
    int totalData = 0;
    foreach (var element in arr) // let's say arr.Count() is 10
    {
        Action<Texture> onImageReceived = (texture) =>
        {
            if (result != null)
            {
                var res = new QueryTextureResult()
                {
                    Texture = texture,
                    QueryId = queryId,
                    Index = totalData // why this one is always 10 if the callback takes time? 
                };

                result(res);

                Debug.Log("INdex: " + res.Index);
            }
        };

        imageManager.GetImage("http://image.url", onImageReceived);

        totalData++;
    }

}

如评论所述,如果我有10个元素,result被调用需要时间,为什么我收到的QueryTextureResult.Index总是10?它是通过参考传递的吗?有什么方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

在您的代码示例中,捕获了totalData,因此所有委托都将引用同一个变量。在循环结束时,totalData的值为10,然后每位代表都会读取相同的totalData,并且会得到10

解决方案是在将变量传递给委托之前获取变量的副本,因此每个委托都有自己的副本。

foreach (var element in arr) // let's say arr.Count() is 10
{
    var copy = totalData;
    Action<Texture> onImageReceived = (texture) =>
    {
        if (result != null)
        {
            var res = new QueryTextureResult()
            {
                Texture = texture,
                QueryId = queryId,
                Index = copy // <== 
            };

答案 1 :(得分:1)

这是因为totalData已关闭,onImageReceived将被异步调用。

假设您有3个项目,它可以按以下顺序执行:

    为项目1声明了
  1. onImageReceived,输出totalData
  2. 为项目1 调用
  3. GetImage
  4. totalData = 1
  5. 为项目2声明的
  6. onImageReceived,输出totalData
  7. 为项目2 调用
  8. GetImage
  9. totalData = 2
  10. 为项目3声明的
  11. onImageReceived,输出totalData
  12. GetImage被称为第3项
  13. totalData = 3
  14. 第1项已完成,调用onImageReceived事件,该事件输出totalData ...现在是3
  15. 第2项已完成,调用onImageReceived个事件,totalData也是3个
  16. 第3项
  17. 相同