【问题标题】:C# integer passed as reference in callback?C# 整数作为回调中的引用传递?
【发布时间】:2017-03-09 15:13:31
【问题描述】:

我在回调和 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?它是通过引用传递的吗?有什么办法解决这个问题?

【问题讨论】:

  • 变量被捕获,它们都共享相同的内存地址。

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


【解决方案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 // <== 
            };

【讨论】:

    【解决方案2】:

    这是因为totalData 被关闭并且onImageReceived 将被异步调用。

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

    1. onImageReceived 为第 1 项声明,输出 totalData
    2. GetImage 为项目 1 调用
    3. totalData = 1
    4. onImageReceived 为第 2 项声明,输出 totalData
    5. GetImage 为第 2 项调用
    6. totalData = 2
    7. onImageReceived 为第 3 项声明,输出 totalData
    8. GetImage 为第 3 项调用
    9. totalData = 3
    10. 第1项完成,调用onImageReceived事件,输出totalData...现在是3
    11. 第2项完成,调用onImageReceived事件,totalData也是3
    12. 第 3 项也一样

    【讨论】:

    • 感谢您的回答,现在有点意思了。所以我猜Index = totalData 仅在调用onImageReceived 之后才被填充,是吗?
    • @andiwinata 是的。您可以设置两个断点:在您的 DoSth 方法的开头,以及在 onImageReceived 操作的开头,看看会发生什么:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多