我使用'添加Web引用'在vusual studio中爲Web服務生成了代理類。生成的RTWebService
類有一個方法SetValueAsync
。我擴展了這個類,並添加了一個記錄請求的SetValueRequest
,並在發生錯誤時取消所有未決請求。每個請求我存儲userState
對象在我作爲創建一個ArrayList如下:爲什麼ArrayList的同步包裝器不起作用?
requests = ArrayList.Synchronized(new ArrayList());
我創建了一個方法:
public void CancelPendingRequests() {
lock (requests.SyncRoot) {
if (requests.Count > 0) {
foreach (object request in requests) {
this.CancelAsync(request);
}
requests.Clear();
}
}
}
我把這種方法當在SetValueCompleted
事件的請求返回:
private void onRequestComplete(
object sender,
Service.SetValueCompletedEventArgs args
) {
lock (syncResponse) {
if (args.Cancelled) {
return;
}
if (args.UserState != null) {
requests.Remove(args.UserState);
}
if (args.Error != null) {
CancelPendingRequests();
}
}
}
要開始一個新的請求我打電話:
public void SetValueRequest(string tag, string value) {
var request = new object();
this.SetValueAsync(tag, value, request);
requests.Add(request);
}
每當我提出請求並同時返回一個錯誤消息時,我在CancelPendingRequests
中得到TargetInvocationException
。內的例外是在CancelPendingRequests
方法說法一個ArrayList一個InvalidOperationException
:
集合已修改;枚舉操作可能不會執行。
所以它似乎SetValueRequest
已修改requests
對象,而我正在枚舉它。我認爲這是不可能的,因爲我使用ArrayList的同步包裝並使用SyncRoot同步枚舉。我有點卡住這個,所以如果有人有一個想法?
你的代碼還是壞了。如果您在迭代時更改列表,則for不會大聲喊出,但是您仍然會遇到競態條件錯誤。 – 2011-02-12 17:19:35