關於監聽回調兩次的原因,可能是因為重新監聽導致的,所以查到微軟上面的解析是說
BeginGetContext方法開始異步 (非阻塞) 調用以接收傳入的客戶端請求。 在調用此方法之前,必須調用 Start 方法,並添加至少一個統一資源標識符 (uri) 前綴,以便通過將 uri 字符串添加到屬性返回的來偵聽 HttpListenerPrefixCollection Prefixes 。
必須通過調用方法完成異步操作 EndGetContext 。 通常,方法由 callback
委托調用。
操作完成時,此方法不會被阻止。 若要獲取傳入請求並在操作完成之前一直阻止,請調用 GetContext 方法。
有關使用異步編程模型的詳細信息,請參閱 以異步方式調用同步方法
我的猜測是這個
下面是寫的一個HttpListener 幫助類
public class HttpListenerServer : IDisposable { private readonly HttpListener _listener; public HttpListenerServer(string[] prefixes) { // 檢查系統是否支持 if (!HttpListener.IsSupported) { throw new ArgumentException("使用 該功能的系統 必須為 Windows XP SP2 或 Server 2003 以上系統!"); } if (prefixes == null || prefixes.Length == 0) { throw new ArgumentException("請填寫監聽地址"); } _listener = new HttpListener(); foreach (string s in prefixes) { _listener.Prefixes.Add(s); } _listener.Start(); _listener.BeginGetContext(new AsyncCallback(GetContextCallBack), _listener); } public void Dispose() { try { if (_listener != null) { _listener.Stop(); _listener.Close(); _listener.Abort(); } RequestHandlerEven = null; } catch (Exception) { } } public delegate object RequestHandler(HttpListenerRequest request); public event RequestHandler RequestHandlerEven; private void GetContextCallBack(IAsyncResult ar) { try { HttpListener httplis = ar.AsyncState as HttpListener; if (httplis.IsListening) { HttpListenerContext context = httplis.EndGetContext(ar); #region 解析Request請求 object resData = null; HttpListenerRequest request = context.Request; if (RequestHandlerEven != null) { resData = RequestHandlerEven(request); } else { resData = new { code = "200", description = "成功", data = "接收數據完成,時間:=" + DateTime.Now }; } #endregion 解析Request請求 #region 構造Response響應 using (HttpListenerResponse response = context.Response) { response.ContentEncoding = Encoding.UTF8; response.ContentType = "application/json;charset=UTF-8"; response.AppendHeader("Content-Type", "application/json;charset=UTF-8"); try { response.StatusCode = (int)HttpStatusCode.OK; string responseString = JsonConvert.SerializeObject(resData, new JsonSerializerSettings() { StringEscapeHandling = StringEscapeHandling.EscapeNonAscii }); using (StreamWriter writer = new StreamWriter(response.OutputStream, Encoding.UTF8)) { writer.Write(responseString); writer.Close(); response.Close(); } } catch (Exception ex) { response.StatusCode = (int)HttpStatusCode.NotFound; response.StatusDescription = "404"; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"在接收數據時發生錯誤:{ex.ToString()}"); //把服務端錯誤信息直接返回可能會導致信息不安全,此處僅供參考 var returnByteArr = Encoding.UTF8.GetBytes($"在接收數據時發生錯誤:{ex.ToString()}");//設置客戶端返回信息的編碼 using (var stream = response.OutputStream) { //把處理信息返回到客戶端 stream.Write(returnByteArr, 0, returnByteArr.Length); stream.Close(); response.Close(); } } } #endregion 構造Response響應 httplis.GetContext(); _listener.BeginGetContext(new AsyncCallback(GetContextCallBack), _listener); } } catch (Exception ex) { throw new ArgumentException(ex.Message); } } }