- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个执行了很长时间的单线程进程。我需要多个用户有权执行此过程,我选择 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);
此外,根据建议,我更改了对 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();
}
}
最佳答案
发布的代码完全可以正常工作:
无法重现。我想这可以回答问题,因为显然您错误地驱动了测试工作负载。我通过反复单击 Fiddler composer 发送按钮来驱动它。
不过,感谢您发布可执行代码。我应该早点尝试!
关于c# - HttpListener 的多线程应答,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34977875/
我正在研究直径协议(protocol)。我在直径堆栈重新启动时遇到有关处理请求/应答/ session 的问题,因此我想知道哪些参数存储在数据库中以供直径堆栈重新启动时进一步使用? Session_I
我正在学习 SOAP,并创建了一个非常小的 CGI 脚本,该脚本在 Apache 上运行,将提供一小组功能。 #!/usr/bin/perl use SOAP::Transport::HTTP; SO
我是 C# 新手,我需要发送 HTTP GET 请求并阅读答案。我熟悉 Java 并且很容易做到 URLConnection 类,但我不知道在 c# 中。有人可以帮忙吗? 最佳答案 最简单的方法是使用
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 1 年前。
我想创建一个从服务器返回 token 的函数,但是 http.post() 在我的函数返回 token 后得到响应。 我如何在返回 token 之前等待 http.post()。 我的代码: impo
此处引用 developer site & call recording android 10尝试录制音频文件并将其保存到其本地目录路径,我使用 AccessibilityService 来实现它在
我是一名优秀的程序员,十分优秀!