【发布时间】:2012-03-31 07:35:33
【问题描述】:
我读过很多文章说 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另一个工作线程被用来执行回调
有什么问题?
【问题讨论】:
-
我很困惑...我们预计回调将在不同的线程上执行。这在很大程度上是使用 Begin*... 的全部意义?注意:使用 Begin/End 回调来打开一个等待句柄是没有意义的 - 如果你要在调用者处等待,你可能根本不使用 Begin*。
-
@MarcGravell,我认为问题是为什么在第二种情况下使用工作线程而不是 IOCP。
-
I/O 完成端口可用于简单的 I/O 请求,由重叠的 Read/WriteFile() 调用启动。 SQL I/O 请求没有什么简单的,中间有一大块软件,称为“SQL Native Client”。以及 System.Data.SqlClient 中的一大段 C++/CLI 代码。 TDS 是协议,SNI 是接口,通道可以命名为管道、套接字或共享内存。所有的文件都记录得很差,拆开眼睛看不到。
标签: c# asynchronous iocp