我写了一个程序关于httpWebRequest异步获取网站内容,在开始时没有什么问题,问题出在关闭所有线程的时候,
已经发出去的异步请求并没有结束,任务管理器中的线程数反而可能会增加(按机器而定),就算异步执行完毕后,
线程并没有减少内存也在不停的增加。
请问这是怎么回事,请牛人解答
代码如下:using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
public class RequestState
{
// This class stores the State of the request.
const int BUFFER_SIZE = 1024;
public StringBuilder requestData;
public byte[] BufferRead;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream streamResponse;
public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
requestData = new StringBuilder("");
request = null;
streamResponse = null;
}
}class HttpWebRequest_BeginGetResponse
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
const int DefaultTimeout = 2 * 60 * 1000; // 2 minutes timeout
public delegate void GetDataHandle(string html);
public event GetDataHandle GetDataEvent; // Abort the request if the timer fires.
private void TimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
}
}
} public void Request()
{ try
{
// Create a HttpWebrequest object to the desired URL.
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.baidu.com");
// Create an instance of the RequestState and assign the previous myHttpWebRequest
// object to its request field.
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result =
(IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback), myRequestState); // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true); // The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne(); // Release the HttpWebResponse resource.
myRequestState.response.Close();
}
catch (WebException e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("\nMessage:{0}", e.Message);
Console.WriteLine("\nStatus:{0}", e.Status);
Console.WriteLine("Press any key to continue..........");
}
catch (Exception e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("Source :{0} ", e.Source);
Console.WriteLine("Message :{0} ", e.Message);
Console.WriteLine("Press any key to continue..........");
Console.Read();
}
} private void RespCallback(IAsyncResult asynchronousResult)
{
try
{
// State of request is asynchronous.
RequestState myRequestState = (RequestState)asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest = myRequestState.request;
myRequestState.response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(asynchronousResult); // Read the response into a Stream object.
Stream responseStream = myRequestState.response.GetResponseStream();
myRequestState.streamResponse = responseStream; // Begin the Reading of the contents of the HTML page and print it to the console.
IAsyncResult asynchronousInputRead = responseStream.BeginRead(myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
catch (WebException e)
{
Console.WriteLine("\nRespCallback Exception raised!");
Console.WriteLine("\nMessage:{0}", e.Message);
Console.WriteLine("\nStatus:{0}", e.Status);
}
allDone.Set();
}
private void ReadCallBack(IAsyncResult asyncResult)
{
try
{ RequestState myRequestState = (RequestState)asyncResult.AsyncState;
Stream responseStream = myRequestState.streamResponse;
int read = responseStream.EndRead(asyncResult);
// Read the HTML page and then print it to the console.
if (read > 0)
{
myRequestState.requestData.Append(Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read));
IAsyncResult asynchronousResult = responseStream.BeginRead(myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
else
{
Console.WriteLine("\nThe contents of the Html page are : ");
if (myRequestState.requestData.Length > 1)
{
string stringContent;
stringContent = myRequestState.requestData.ToString();
GetDataEvent("成功获取");
Console.WriteLine(stringContent);
}
Console.WriteLine("Press any key to continue..........");
Console.ReadLine(); responseStream.Close();
} }
catch (WebException e)
{
Console.WriteLine("\nReadCallBack Exception raised!");
Console.WriteLine("\nMessage:{0}", e.Message);
Console.WriteLine("\nStatus:{0}", e.Status);
}
allDone.Set(); }
}
已经发出去的异步请求并没有结束,任务管理器中的线程数反而可能会增加(按机器而定),就算异步执行完毕后,
线程并没有减少内存也在不停的增加。
请问这是怎么回事,请牛人解答
代码如下:using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
public class RequestState
{
// This class stores the State of the request.
const int BUFFER_SIZE = 1024;
public StringBuilder requestData;
public byte[] BufferRead;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream streamResponse;
public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
requestData = new StringBuilder("");
request = null;
streamResponse = null;
}
}class HttpWebRequest_BeginGetResponse
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
const int DefaultTimeout = 2 * 60 * 1000; // 2 minutes timeout
public delegate void GetDataHandle(string html);
public event GetDataHandle GetDataEvent; // Abort the request if the timer fires.
private void TimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
}
}
} public void Request()
{ try
{
// Create a HttpWebrequest object to the desired URL.
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.baidu.com");
// Create an instance of the RequestState and assign the previous myHttpWebRequest
// object to its request field.
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result =
(IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback), myRequestState); // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true); // The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne(); // Release the HttpWebResponse resource.
myRequestState.response.Close();
}
catch (WebException e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("\nMessage:{0}", e.Message);
Console.WriteLine("\nStatus:{0}", e.Status);
Console.WriteLine("Press any key to continue..........");
}
catch (Exception e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("Source :{0} ", e.Source);
Console.WriteLine("Message :{0} ", e.Message);
Console.WriteLine("Press any key to continue..........");
Console.Read();
}
} private void RespCallback(IAsyncResult asynchronousResult)
{
try
{
// State of request is asynchronous.
RequestState myRequestState = (RequestState)asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest = myRequestState.request;
myRequestState.response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(asynchronousResult); // Read the response into a Stream object.
Stream responseStream = myRequestState.response.GetResponseStream();
myRequestState.streamResponse = responseStream; // Begin the Reading of the contents of the HTML page and print it to the console.
IAsyncResult asynchronousInputRead = responseStream.BeginRead(myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
catch (WebException e)
{
Console.WriteLine("\nRespCallback Exception raised!");
Console.WriteLine("\nMessage:{0}", e.Message);
Console.WriteLine("\nStatus:{0}", e.Status);
}
allDone.Set();
}
private void ReadCallBack(IAsyncResult asyncResult)
{
try
{ RequestState myRequestState = (RequestState)asyncResult.AsyncState;
Stream responseStream = myRequestState.streamResponse;
int read = responseStream.EndRead(asyncResult);
// Read the HTML page and then print it to the console.
if (read > 0)
{
myRequestState.requestData.Append(Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read));
IAsyncResult asynchronousResult = responseStream.BeginRead(myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
else
{
Console.WriteLine("\nThe contents of the Html page are : ");
if (myRequestState.requestData.Length > 1)
{
string stringContent;
stringContent = myRequestState.requestData.ToString();
GetDataEvent("成功获取");
Console.WriteLine(stringContent);
}
Console.WriteLine("Press any key to continue..........");
Console.ReadLine(); responseStream.Close();
} }
catch (WebException e)
{
Console.WriteLine("\nReadCallBack Exception raised!");
Console.WriteLine("\nMessage:{0}", e.Message);
Console.WriteLine("\nStatus:{0}", e.Status);
}
allDone.Set(); }
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace TestThread
{
public partial class Form1 : Form
{
List<Thread> listThread = new List<Thread>();
bool blTag; public Form1()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;
} private void button1_Click(object sender, EventArgs e)
{
Thread newThread = null;
for(int i=0;i<20;i++)
{
newThread = new Thread(process);
newThread.Start();
listThread.Add(newThread);
}
this.button2.Enabled = true;
this.button1.Enabled = false;
}
HttpWebRequest_BeginGetResponse instance;
private void process()
{
instance = new HttpWebRequest_BeginGetResponse();
instance.GetDataEvent += new HttpWebRequest_BeginGetResponse.GetDataHandle(instance_GetDataEvent);
while (!blTag)
{
instance.Request();
}
} void instance_GetDataEvent(string html)
{
this.textBox1.AppendText(html+"r\n");
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.Focus();
} private void button2_Click(object sender, EventArgs e)
{
blTag = true;
foreach (Thread newThread in listThread)
{
newThread.Abort();
} this.button1.Enabled = true;
this.button2.Enabled = false; foreach (Thread newThread in listThread)
{
if (newThread.IsAlive == true)
return;
}
listThread.Clear();
}
}
}
Async 调用机制跟 Thread/ ManualResetEvent 混合使用有点乱
private void process()
{
instance = new HttpWebRequest_BeginGetResponse();
instance.GetDataEvent += new HttpWebRequest_BeginGetResponse.GetDataHandle(instance_GetDataEvent);
while (!blTag) // 主要问题在这里 线程中还在循环,这里每循环一次由于你的request是异步的 都会产生新的线程 瞬间可能打到线程上限
{
instance.Request();
}
}
void instance_GetDataEvent(string html) //跨线程操作textBox ,会有问题
{
this.textBox1.AppendText(html+"r\n");
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.Focus();
}
foreach (Thread newThread in listThread) //你根本不只20个线程
{
newThread.Abort();
}
不是那儿的问题
你使用的问题
可能代码不完整.不知道你哪里用到了自己new出来的那20个线程.
委托异步会自己建线程.当然.net在委托方法后会自动帮你关掉。
你不按button2.一直会建立新线程.太不可取了吧.
好象并没有直接获取当前运用程序线程数量的函数。
自己想办法判断吧.
用一个 int 来记录?调用方法前+1.结束后-1?
就算你手动关掉.你那个while (!blTag)语句.什么电脑受的了。
异步委托方法结束后并不会结束异步产生的线程。
所以测试了了下。
大哥,你的代码是从别的地方copy过来的吧.呵呵。
void instance_GetDataEvent(string html)
{
this.textBox1.AppendText(html+"r\n");
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.Focus();
}
这个代码我不知道你是否可以执行.
异步建立的线程.回调这个函数.但是这个线程的上下文应该是不会存在textbox1的。除非你在次线程中new了它.
或者是你代码不完整.还有你的代码中本来就是ThreadPool.线程池了。到前台开多线程不知道什么用意.
而且.你获取的是一个网页的数据.并不是多个网页.用多线程怎么处理?我搞晕了。我用了你前面的代码.后面写一点代码就可以了。private void button1_Click(object sender, EventArgs e)
{
HttpWebRequest_BeginGetResponse instance = new HttpWebRequest_BeginGetResponse();
instance.GetDataEvent += new HttpWebRequest_BeginGetResponse.GetDataHandle(instance_GetDataEvent);
instance.Request();
} void instance_GetDataEvent(string html)
{
MessageBox.Show(html);
}前面代码
ReadCallBack(IAsyncResult asyncResult)这个方法string stringContent;
stringContent = myRequestState.requestData.ToString();
GetDataEvent(stringContent);不把数据传递给 回调函数.
前面怎么显示出数据???
把你代码贴出来吧.可能是我理解错你的意思。
委托的异步所建立的线程.在方法完成之后,应该就被.net放入回收站,等待回收吧?
知道的说下。我不清楚。
{
this.textBox1.AppendText(html+"r\n");
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.Focus();
} 这一句是可以执行的,在ReadCallBack中有一句GetDataEvent("成功获取");调用这个方法
还有我这里并没有用到线程池这里并没有跨线程操作,在Init方法中我加 CheckForIllegalCrossThreadCalls = false;
来保证跨线程调用UI安全希望知道的朋友给个话出来,谢谢
你这里是获取网页,应该可以直接使用
看下书的概念.做个例子不会难.不需要牛人来。自己就可以搞定.
主动解决问题才是学习的手段.
GC.CollectionCount(0);