我读过许多文章说IOCP用于BeginXX / EndXX对调用。 但是,当我测试它们时,我的结果显示IOCP在BeginExecuteReader调用中不起作用,而它在BeginGetResponse调用中工作正常。
我对这个结果非常困惑。谁能告诉我原因?我的测试代码有什么问题吗?
以下是测试:
使用BeginGetResponse进行测试
代码:
public static void IoThread2()
{
ThreadPool.SetMinThreads(5, 3);
ThreadPool.SetMaxThreads(5, 3);
int w; int io;
ThreadPool.GetAvailableThreads(out w, out io);
int cid = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Begin:" + w.ToString() + ";" + io.ToString() + "; id = " + cid.ToString());
ManualResetEvent waitHandle = new ManualResetEvent(false);
WebRequest request = HttpWebRequest.Create("http://www.cnblogs.com/");
AsyncCallback cb = new AsyncCallback(IOThread2CallBack);
request.BeginGetResponse(cb, request);
waitHandle.WaitOne();
}
public static void IOThread2CallBack(IAsyncResult ar)
{
try
{
WebRequest request = (WebRequest)ar.AsyncState;
int w2; int io2;
ThreadPool.GetAvailableThreads(out w2, out io2);
int cid2 = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("End:" + w2.ToString() + ";" + io2.ToString() + "; id = " + cid2.ToString());
var response = request.EndGetResponse(ar);
}catch (Exception ex){ }
}
结果:
Begin:5;3; id = 10
End:5;2; id = 13
使用一个IO线程来执行回调。
使用BeginExecuteReader进行测试 代码:
public static void IoThread1()
{
ThreadPool.SetMinThreads(5, 3);
ThreadPool.SetMaxThreads(5, 3);
int w; int io;
ThreadPool.GetAvailableThreads(out w, out io);
int cid = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Begin:" + w.ToString() + ";" + io.ToString() + "; id = " +
cid.ToString());
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
AsyncCallback da = new AsyncCallback(IoThreadCallBack);
SqlCommand command = new SqlCommand(s_QueryDatabaseListScript, connection);
IAsyncResult ir = command.BeginExecuteReader(da,
command,System.Data.CommandBehavior.CloseConnection);
ManualResetEvent waitHandle = new ManualResetEvent(false);
waitHandle.WaitOne();
}
public static void IoThreadCallBack(IAsyncResult ar)
{
int w; int io;
ThreadPool.GetAvailableThreads(out w, out io);
int cid = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("End:" + w.ToString() + ";" + io.ToString() + "; id = " +
cid.ToString());
SqlCommand command = (SqlCommand)ar.AsyncState;
StringBuilder sb = new StringBuilder();
try
{
using (SqlDataReader reader = command.EndExecuteReader(ar))
{
while (reader.Read())
{
sb.Append(reader.GetString(0)).Append("; ");
}
}
}
catch (Exception ex){ }
finally
{
command.Connection.Close();
}
}
结果:
Begin:5;3; id = 10
End:4;3; id = 7
另一个工作线程用于执行回调
有什么问题?
答案 0 :(得分:0)
你的repro很有创意。这是一个有趣的案例。
尝试使用命令文本“WAITFOR DELAY '02:00'启动100个SqlCommands;”并观察线程计数随时间的变化(启动打印统计信息的计时器)。
我的猜测是,我们会看到消耗的线程少于100个(意味着这部分异步行为正在发挥作用)。由于某种原因,SqlCommand正在使用“错误的”线程池线程,但这可能根本不会降低可伸缩性。