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

本文关键字:引用 整数 回调 | 更新日期: 2023-09-27 18:15:14

我有一点问题与回调和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#整数在回调中作为引用传递

这是因为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项同

在您的代码示例中,捕获了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 // <== 
            };