我在 c# .NET 中实现了一个 HTTP 服务器:
public class HttpServer
{
private HttpListener listener;
public HttpServer()
{
listener = new HttpListener();
listener.Prefixes.Add("http://localhost:8080/");
}
public void Start()
{
lock(this) {
listener.Start();
AsyncProcessing(listener);
}
}
public void Stop()
{
lock (this) {
listener.Stop();
}
}
private void AsyncProcessing(HttpListener listener)
{
if (listener == null)
return;
listener.BeginGetContext(new AsyncCallback(Callback), listener);
}
private void Callback(IAsyncResult result)
{
HttpListenerContext context = null;
lock(this) {
HttpListener listener = (HttpListener)result.AsyncState;
if (!listener.IsListening)
return;
context = listener.EndGetContext(result);
AsyncProcessing(listener);
}
/* handle request */
}
}
我对这个实现有一些疑问:
- 我在这里和那里添加了一些锁来防止竞争条件,但我很困惑:真的需要那些吗?我在文档中读到所有公共(public)非静态方法都不是线程安全的。为什么我没有看到考虑到这一事实的代码?
- HttpListenerContext 的行为如何?他与 HttpListener 有某种联系吗?或者我可以同时使用多个 HttpListenerContext 吗?
- 我听说 HttpListener 不能用于生产系统,但我从未见过支持这种说法的论据。是真是假?
- 是否还有其他我应该考虑但未提及的事项?
谢谢你的想法
最佳答案
请记住,我不是多线程方面的专家,因此您应该尽可能地注意验证我所说的任何内容。
如果其他人知道,并且想窃取我的全部答案并编辑或更正细节,请随意这样做。
让我们一一解答您的问题:
I added some locks here and there to prevent race conditions, but I'm confused: Are those really needed? I read in the documentation that all public non-static methods are NOT thread safe. Why haven't I seen code where this fact is considered?
好吧,是的,不是。锁通常用于防止多个线程同时访问同一数据结构,因为它会破坏数据结构。考虑在一个线程上对数组进行排序,并在另一个线程的中间插入一个元素,正确地为这两个线程计时会破坏数组的内容。
现在,在您的代码中,您锁定了 this
,这绝不是一个好主意。外部代码可能也锁定了同一个对象,这是你无法控制的,所以为了创建生产就绪代码,我不会那样做。
如果您的代码需要锁,我会构造特定的锁对象并使用它们。
换句话说,添加:
private readonly object _Lock = new object();
然后在所有有 lock(this)
的地方将其替换为 lock(_Lock)
。这样,如果需要,您还可以拥有多个锁。
至于是否真的需要锁,我不是 100% 确定。我不确定的是您在调用 Stop 之前锁定,并且在回调中锁定并在锁定内检查监听器是否仍在运行。
这将防止您在接受请求后但在实际处理请求之前停止监听器。换句话说,听起来您会在打开请求仍在处理的情况下阻止关闭服务器。
但是,不,你不会阻止它,因为你可能会在回调中离开锁定部分后停止服务器,但在注释代码完全执行期间或之前,所以你仍然会遇到这个问题。
但是 这也意味着您已经有效地序列化了一些回调方法,即您调用 EndGetContext 并重新启动 BeginGetContext 循环的部分。我不知道这是否是一个好的模式。
How does the HttpListenerContext behave? Does he have some sort of connection to the HttpListener? Or can I use multiple HttpListenerContexts concurrently?
这里我来猜一猜。该类没有对监听器类的引用,或,它有一种线程安全的方式与之合作。
如果对请求/响应数据的每次访问都必须序列化,那么它就不是一个基于线程的 http 监听器系统。
无论如何,如果有疑问,请检查您正在访问的上下文类的方法和/或属性的文档,如果您需要采取措施确保线程安全,文档会这样说。
I heard HttpListener wouldn't be ready for production systems, but I've never seen an argument supporting this claim. Is it true or not?
(见问题评论)
Are there other things I should consider which I haven't mentioned?
多线程代码难以编写。从你的问题来看,我会大胆猜测你没有做很多,老实说,虽然我做了很多,但我仍然觉得我如履薄冰。
因此,我的建议如下:
- 您真的需要多线程吗?
- 您是否有其他对此了解更多的同事可以帮助您?
关于c# - 生产就绪,多线程 c# http 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6371741/