调用一个委托却执行了两次

Imcx 2017-02-15 10:57:04


private HttpListener httpListener = new HttpListener();

public void Start(AsyncCallback callback)
{
httpListener.Start();
httpListener.BeginGetContext(endGetContext, callback);
}

private void endGetContext(IAsyncResult ar)
{
var callback = ar.AsyncState as AsyncCallback;

/*
* 下面创建了一个IAsyncResult
* 主要是为了把HttpListenerContext传递出去
*/
callback(ACTransfer.Create(new HttpContext(httpListener.EndGetContext(ar))));
if (httpListener != null)
{
httpListener.BeginGetContext(endGetContext, callback);//开始监听下一个
}
}

...全文
154 点赞 收藏 12
写回复
12 条回复
Imcx 2017年02月15日
回复 点赞
Imcx 2017年02月15日
救命啦
回复 点赞
Imcx 2017年02月15日
还有,从本地访问服务器也试过,会执两次
回复 点赞
理论自信不靠删贴 2017年02月15日
引用 1 楼 Imcx_ 的回复:
... 2.用浏览器直接访问,每次返回的值都是2的倍数 3.去掉黄色部分代码加断点就只停止一次
浏览器可能要访问/favicon,用来浏览器栏显示网站的小图标。 建议你调试时检查context.Request.Url。
回复 点赞
Imcx 2017年02月15日
目前只发现如果加上了响应请求的代码就会执行两次 PS: 我还试过 1.在外面使用非匿名的方法 2.把响应请求的代码放到方法里 3.不使用using语法糖 这些都会跑两次
回复 点赞
Imcx 2017年02月15日

//从其他地方调用方法
.Start((ar) =>
{
    var context = ar.AsyncState as HttpContext;
    var request = context.Request;

    using (var writer = new System.IO.StreamWriter(context.Response.OutputStream))
    {
        writer.Write("return: " + i++);//这个i只是测试用的一个全局变量
    }
});

1.在这个匿名委托中加上断点,会停止两次 2.用浏览器直接访问,每次返回的值都是2的倍数 3.去掉黄色部分代码加断点就只停止一次
回复 点赞
Imcx 2017年02月15日
已经修改了,简单说明下,这里是自己写的一个HttpServer的类,用来接收一些简单的获取数据的请求,里面有一些相关业务的处理方法 通过实例化添加一个url到httpListener里去,外部通过

public void Start(Action<HttpListenerContext> callback)
{
    httpListener.Start();
    httpListener.BeginGetContext(endGetContext, callback);
}
开始接收并处理请求

HttpServer.Start((context) =>
{
    var request = context.Request;//用来访问请求
    //这里做些处理...
    using (var writer = new System.IO.StreamWriter(context.Response.OutputStream))
    {
        writer.Write("response");//响应消息
    }
});
我想请问的就是上面的代码会被执行两次是什么原因
回复 点赞
Imcx 2017年02月15日
引用 10 楼 sp1234_maJia 的回复:
如果你担心有没有先调用 EndGetContext语句(我并没有测试),你可以先调用它
private void endGetContext(IAsyncResult ar)
{
    var callback = ar.AsyncState as Action<HttpListenerContext>;
    var context = httpListener.EndGetContext(ar);
    httpListener.BeginGetContext(endGetContext, callback);//开始监听下一个
    callback(context);
}
但是,总之是先提高 I/O 效率,然后才 callback 业务处理。
非常感谢你的建议,我写过来的时候是把注释的代码删除了的,事实callback是写在最后面的 另外这个回调的参数是我自己封装的一个类,不过写在我先试试你说的这种
回复 点赞
sp1234_maJia 2017年02月15日
如果你担心有没有先调用 EndGetContext语句(我并没有测试),你可以先调用它
private void endGetContext(IAsyncResult ar)
{
    var callback = ar.AsyncState as Action<HttpListenerContext>;
    var context = httpListener.EndGetContext(ar);
    httpListener.BeginGetContext(endGetContext, callback);//开始监听下一个
    callback(context);
}
但是,总之是先提高 I/O 效率,然后才 callback 业务处理。
回复 点赞
以专业开发人员为伍 2017年02月15日
所谓“调用代码”是这样写的
.Start((context) =>
{
    using (var writer = new System.IO.StreamWriter(context.Response.OutputStream))
    {
        writer.Write("return: " + i++);//这个i只是测试用的一个全局变量
    }
});
直接使用 HttpListenerContext 来输出。注意不是 HttpContext,而是 HttpListenerContext。
回复 点赞
以专业开发人员为伍 2017年02月15日
callback 应该在“开始监听下一个”之后,应该及时先去监听下一个,而不是先回调然后才监听下一个。
回复 点赞
以专业开发人员为伍 2017年02月15日
看不懂你创建一个 HttpContext 对象是啥的呢?
private HttpListener httpListener = new HttpListener();

public void Start(Action<HttpListenerContext> callback)
{
    httpListener.Start();
    httpListener.BeginGetContext(endGetContext, callback);
}

private void endGetContext(IAsyncResult ar)
{
    var callback = ar.AsyncState as Action<HttpListenerContext>;
    httpListener.BeginGetContext(endGetContext, callback);//开始监听下一个
    callback(httpListener.EndGetContext(ar));
}
就这么几句代码,让你写的“稀碎”。
回复 点赞
发动态
发帖子
C#
创建于2007-09-28

8.5w+

社区成员

64.0w+

社区内容

.NET技术 C#
社区公告
暂无公告