所以我想排队一些要调用的动作。
一点背景:尝试使用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时,散列被更改为第一个集合(在队列中)到“”。
这周围有吗?
感谢。
答案 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 并捕获status
和hash
变量。
快速解决方案是创建另一个变量,而不是将其捕获:
string capturedHash = hash;
temp_actions.Enqueue(() => auth.change_status_multiple(status, capturedHash));