我问这些问题,因为我在多线程代码中的异步请求中使用CookieContainer。我不能把一个异步请求放在一个锁中。也许我必须像F#一样使用只读“变量”(或不可变类型),对吗?
答案 0 :(得分:6)
不,并非所有.NET类都是线程安全的。事实上,很少有人需要。一般来说,静态成员应该是线程安全的,但这就是它。
不可变/半不可变对象是自动线程安全的(这包括像XslTransform之类的东西) - 并且有一些可变的情况(例如线程容器),你可以期望事情是线程安全的。 MSDN声明了每个类的线程安全性。
我不希望cookie容器是线程安全的,所以你可能需要自己同步。
(更新)
重申你的第二点;究竟你想到哪些变量?在异步请求期间,您自己的本地状态变量不会直接更新,因此在处理响应时准备请求时,您只需同步访问即可。最常见的是,通过Monitor
- 即
lock(syncLock) {
// prepare request from (synchronized) state
req.Begin{...}
}
然后在回调中
lock(syncLock) {
// ...read values from request...
// ...update local state...
}
syncLock
只是一个锁定对象(可能是针对某个实例):
private readonly object syncLock = new object();
答案 1 :(得分:5)
来自horses mouth:
线程安全
此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。
编辑:
您可以锁定修改实例成员的操作。
答案 2 :(得分:3)
正如我所看到的(在Reflector的帮助下),CookieContainer在内部使用锁来访问其成员,因此尽管有文档,它应该是线程安全的。
顺便说一下,它根本没有公共静态成员。所以在我看来,文档只提供标准通知。
答案 3 :(得分:2)
只需注意,网页会将修改后的Cookie列表作为其HTTP回复的一部分发送。在发送回复后修改CookieContainer将无法完成任何操作 - 您只需修改不再存在的页面请求的cookie集合。
答案 4 :(得分:0)
Microsoft保证.NET框架中的所有静态类都是线程安全的。
您可以使用Reflector验证这一点。