Ich habe viele Artikel gelesen sagen, dass IOCP in BeginXX/EndXX-Paaren verwendet wird. Wenn ich sie jedoch teste, zeigte mein Ergebnis, dass IOCP nicht im BeginExecuteReader-Aufruf funktionierte, während es im BeginGetResponse-Aufruf problemlos funktionierte.Warum IOCP nicht in BeginExecuteReader funktioniert
Ich bin sehr verwirrt mit diesem Ergebnis. Kann mir jemand den Grund sagen? Stimmt etwas mit meinem Testcode nicht?
Hier ist der Test unter:
Test mit BeginGetResponse
Code:
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){ } }
Ergebnis:
Begin:5;3; id = 10 End:5;2; id = 13
Ein IO-Thread verwendet wurde, den Rückruf auszuführen .
Test mit BeginExecuteReader Code:
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(); } }
Ergebnis:
Begin:5;3; id = 10 End:4;3; id = 7
Ein weiteres Werk Thread verwendet wurde den Rückruf
Was ist das Problem ausführen?
Ich bin verwirrt ... Wir * erwarten * der Rückruf an einem anderen Thread ausgeführt werden. Das ist weitgehend ** der ganze Punkt ** der Verwendung von Begin * ...? Hinweis: Wenn Sie einen Begin/End-Callback verwenden, um nur einen Wait-Handle zu öffnen, ist das sinnlos. Wenn Sie beim Aufrufer warten, können Sie Begin * ebenfalls nicht verwenden. –
@MarcGravell, ich denke, die Frage ist, warum wurde ein Arbeiter-Thread im zweiten Fall und nicht ein IOCP verwendet. – svick
E/A-Completion-Ports sind für einfache E/A-Anforderungen verfügbar, die durch einen überlappenden Read/WriteFile() - Aufruf gestartet werden. Es gibt nichts Einfaches an einer SQL-I/O-Anfrage, dazwischen sitzt ein großer Haufen Software, der "SQL Native Client". Sowie ein Stück C++/CLI-Code in System.Data.SqlClient. TDS ist das Protokoll, SNI ist die Schnittstelle, der Kanal kann Pipes, Sockets oder Shared Memory genannt werden. Alles ziemlich schlecht dokumentiert und unsichtbar zu zerlegen Augen. –