0

所以我想排队一些要调用的动作。

一点背景知识:尝试使用 Webclient 发送请求,但显然它不允许很长的 URL(超过 2000 个字符),并且在我的系统中发现该值的上限约为 40 个项目(确切地说是 43 个)。所以我需要将 Webclient 请求分成 40~ 组,并决定使用队列来这样做。

这是代码:

  public void some_method()
        int num = 40; // readonly variable declared at top but put here for clarity
        String hash = "";
        Queue<Action> temp_actions = new Queue<Action>();
        foreach (ItemViewModel item in collection)
        {
            num--;
            hash += "&hash=" + item.Hash; // Add &hash + hash to hash

            if (num == 0)
            {
                // Change status for these 40 items
                temp_actions.Enqueue(() => auth.change_status_multiple(status, hash));

                // Reset variables
                num = 40;
                hash = "";
            }
        }

        // Enqueue the last action for the rest of the items
        // Since "num == 0" doesn't cater for leftovers
        // ie. 50 items and 40 in first set, 10 left (which will be enqueued here)
        temp_actions.Enqueue(() => auth.change_status_multiple(status, hash));


        // Start the change status process
        temp_actions.Dequeue().Invoke();

        actions = temp_actions;
    }

    public Queue<Action> actions { get; set; }

    // Event handler for when change_status_multiple fires its event for finish
    private void authentication_MultipleStatusChanged(object sender, EventArgs e)
    {
        if (actions.Count > 0) // Check if there are actions to dequeue
            actions.Dequeue().Invoke();
    }

但是在运行时,哈希将是“”。例如,我有 50 个项目,40 个将在第一个动作中排队,然后 10 个在第二个中,但是第一个集合的哈希字符串是“”。这是为什么?我会认为在将操作排入队列时,它会保留我当时提供的变量的任何值。

我调试了我的代码,在将第一组排入队列时,哈希是正确的,但是当它重置变量 num 和哈希时,第一组(队列内)的哈希更改为“”。

有没有办法解决?

谢谢。

4

2 回答 2

2

您是延迟执行的受害者...您正在hash以下行的委托中捕获范围:

temp_actions.Enqueue(() => auth.change_status_multiple(status, hash));
//...
hash = "";  //happens before delegate above has executed

然后立即清除hash为“”。

当委托运行时,hash已经被清除。

要修复,请获取本地副本hash

var hashCopy = hash;
temp_actions.Enqueue(() => auth.change_status_multiple(status, hashCopy));
//...
hash = "";
于 2012-11-26T10:01:47.030 回答
1

这是因为您的 lambda 表达式创建了一个闭包并捕获了statusandhash变量。

快速解决方案是创建另一个变量,它将被捕获:

string capturedHash = hash;
temp_actions.Enqueue(() => auth.change_status_multiple(status, capturedHash));
于 2012-11-26T10:04:52.807 回答