在调用时排队<action>错误参数</action>

时间:2012-11-26 09:55:42

标签: c# windows-phone-7 queue action

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

一点背景:尝试使用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和hash时,散列被更改为第一个集合(在队列中)到“”。

这周围有吗?

感谢。

2 个答案:

答案 0 :(得分: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 = "";

答案 1 :(得分:1)

这是因为您的lambda表达式会创建 closure 并捕获statushash变量。

快速解决方案是创建另一个变量,而不是将其捕获:

string capturedHash = hash;
temp_actions.Enqueue(() => auth.change_status_multiple(status, capturedHash));