我使用'添加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