gpt4 book ai didi

c# - HttpListener 的多线程应答

转载 作者:太空狗 更新时间:2023-10-29 21:26:54 32 4
gpt4 key购买 nike

我有一个执行了很长时间的单线程进程。我需要多个用户有权执行此过程,我选择 http 协议(protocol)来管理调用。

自然地,当一个进程在工作时,其他人应该等到它完成。如果进程可用,它就会执行。如果不是,则发送 BUSY 应答。

这里是实现:

using System;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace simplehttp
{
class Program
{
private static System.AsyncCallback task;
private static System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);// Notifies one or more waiting threads that an event has occurred.
private static HttpListenerContext workingContext = null;

public static bool isBackgroundWorking()
{
return mre.WaitOne(0);
}
static void Main(string[] args)
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
while (true)
{
Console.WriteLine(" waitOne " + isBackgroundWorking());
mre.WaitOne(); // Blocks the current thread until the current WaitHandle receives a signal.
Console.WriteLine(" do job" + " [" + Thread.CurrentThread.Name + ":" + Thread.CurrentThread.ManagedThreadId + " ]\n");
HttpListenerRequest request = workingContext.Request;
HttpListenerResponse response = workingContext.Response;
string responseString = "WORK " + DateTime.Now ;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
Thread.Sleep(10000);
output.Write(buffer, 0, buffer.Length);
output.Close();
Console.WriteLine(" " + responseString + "\t" + DateTime.Now);
workingContext = null;
mre.Reset(); // Sets the state of the event to nonsignaled, causing threads to block.
}
}).Start();

// Create a listener.
HttpListener listener = new HttpListener();

listener.Prefixes.Add("http://localhost:6789/index/");
listener.Start();
Console.WriteLine("Listening..." + " [" + Thread.CurrentThread.Name + ":" + Thread.CurrentThread.ManagedThreadId + " ]\n");

task = new AsyncCallback(ListenerCallback);

IAsyncResult resultM = listener.BeginGetContext(task,listener);
Console.WriteLine("Waiting for request to be processed asyncronously.");

Console.ReadKey();
Console.WriteLine("Request processed asyncronously.");
listener.Close();
}

private static void ListenerCallback(IAsyncResult result)
{
HttpListener listener = (HttpListener) result.AsyncState;

//If not listening return immediately as this method is called one last time after Close()
if (!listener.IsListening)
return;

HttpListenerContext context = listener.EndGetContext(result);
listener.BeginGetContext(task, listener);

if (workingContext == null && !isBackgroundWorking())
{
// Background work
workingContext = context;
mre.Set(); //Sets the state of the event to signaled, allowing one or more waiting threads to proceed.
}
else
{
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string responseString = "BUSY "+ DateTime.Now + " [" + Thread.CurrentThread.Name + ":" + Thread.CurrentThread.ManagedThreadId;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
Console.WriteLine(responseString + "\t" + DateTime.Now);
}
}
}
}

为了测试,我进行了 2 个 http 调用。我希望有 2 个不同的答案 WORK 和 BUSY。但是我看到第二个请求先等待完成然后执行。

      waitOne False
Listening... [:10 ]

Waiting for request to be processed asyncronously.
do job [:11 ]

WORK 1/24/2016 10:34:01 AM 1/24/2016 10:34:11 AM
waitOne False
do job [:11 ]

WORK 1/24/2016 10:34:11 AM 1/24/2016 10:34:21 AM
waitOne False

我对它应该如何工作的理解有什么问题?

更新(SO 不鼓励太多评论):我的代码看起来很尴尬,因为它是真实过程的复制。在“我的”应用程序中,工作进程是主进程,它在某些特定时刻“有礼貌”地运行嵌入式 C# 代码。因此,我无法运行新任务来处理请求,而且它必须是异步的,因为工作进程会完成自己的工作,并且仅在数据可用时调用从属代码段来通知客户端。它是异步的,因为代码被调用并且应该尽快完成,否则它将阻塞主应用程序。我将尝试通过同步调用添加额外的线程,看看它是否会影响情况。

此示例中未使用调试器,以免干扰打印到控制台的实时进程和时间戳。调试非常好,也是必要的,但在这种情况下,我尝试用输出代替,以避免在同步/等待场景中出现额外的参与者。

应用程序本身并不是繁重的对话。 1-3个客户很少向主应用询问答案。 http协议(protocol)用于方便而不是用于繁重或经常的对话。似乎某些浏览器(如 IE)运行良好(Windows 到 Windows 对话?),而某些浏览器(如 Chrome)(更多系统不可知论者)复制了我的应用程序行为。查看时间戳,Chrome、IE、IE、Chrome 和最后一个 Chrome 仍然进入 WORK 进程。顺便说一句,每个对话建议都会更改代码,现在在检索到上一个请求后会立即发出新请求。

    HttpListenerContext context = listener.EndGetContext(result);
listener.BeginGetContext(task, listener);

enter image description here

此外,根据建议,我更改了对 syncroniuos 的异步调用,结果仍然相同

private static void ListenerCallback(IAsyncResult result)
{
HttpListener listener = (HttpListener) result.AsyncState;

//If not listening return immediately as this method is called one last time after Close()
if (!listener.IsListening)
return;

HttpListenerContext context = listener.EndGetContext(result);

while (true)
{
if (workingContext == null && !isBackgroundWorking())
{
// Background work
workingContext = context;
mre.Set(); //Sets the state of the event to signaled, allowing one or more waiting threads to proceed.
}
else
{
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string responseString = "BUSY " + DateTime.Now + " [" + Thread.CurrentThread.Name + ":" +
Thread.CurrentThread.ManagedThreadId;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
Console.WriteLine(responseString + "\t" + DateTime.Now);
}
context=listener.GetContext();
}
}

最佳答案

发布的代码完全可以正常工作:

enter image description here

无法重现。我想这可以回答问题,因为显然您错误地驱动了测试工作负载。我通过反复单击 Fiddler composer 发送按钮来驱动它。

不过,感谢您发布可执行代码。我应该早点尝试!

关于c# - HttpListener 的多线程应答,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34977875/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com