Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Model panggilan balik dan polling untuk menangani operasi asinkron berguna ketika aplikasi Anda hanya memproses satu operasi asinkron pada satu waktu. Model Wait menyediakan cara yang lebih fleksibel untuk memproses beberapa operasi asinkron. Ada dua model Wait, dinamai untuk metode WaitHandle yang digunakan untuk mengimplementasikannya: model Wait (Apa pun) dan model Wait (Semua).
Untuk menggunakan model Wait, Anda perlu menggunakan AsyncWaitHandle properti objek IAsyncResult yang dikembalikan oleh metode BeginExecuteNonQuery, BeginExecuteReader, atau BeginExecuteXmlReader. Metode WaitAny dan WaitAll keduanya mengharuskan Anda mengirim objek WaitHandle sebagai argumen, yang dikelompokkan bersama dalam array.
Kedua metode Wait memantau operasi asinkron, menunggu penyelesaian. Metode WaitAny ini menunggu salah satu operasi selesai atau kehabisan waktu. Setelah Anda mengetahui operasi tertentu selesai, Anda dapat memproses hasilnya dan kemudian melanjutkan menunggu operasi berikutnya selesai atau kehabisan waktu. Metode WaitAll menunggu semua proses dalam array instans WaitHandle selesai atau kehabisan waktu sebelum melanjutkan.
Manfaat model Wait paling mencolok ketika Anda perlu menjalankan beberapa operasi dengan panjang tertentu di server yang berbeda, atau ketika server Anda cukup kuat untuk memproses semua kueri secara bersamaan. Dalam contoh yang disajikan di sini, tiga kueri meniru proses panjang dengan menambahkan perintah WAITFOR dengan panjang yang bervariasi untuk kueri SELECT yang tidak konsekuensial.
Contoh: Model tunggu (Apa pun)
Contoh berikut mengilustrasikan model Wait (Apa pun). Setelah tiga proses asinkron dimulai, metode WaitAny ini dipanggil untuk menunggu penyelesaian salah satunya. Saat setiap proses selesai, metode EndExecuteReader dipanggil dan objek SqlDataReader yang dihasilkan dibaca. Pada titik ini, aplikasi dunia nyata kemungkinan akan menggunakan SqlDataReader untuk mengisi sebagian halaman. Dalam contoh sederhana ini, waktu proses selesai ditambahkan ke kotak teks yang sesuai dengan proses. Diambil bersama-sama, waktu dalam kotak teks mengilustrasikan titik: Kode dijalankan setiap kali proses selesai.
Untuk menyiapkan contoh ini, buat proyek Situs Web ASP.NET baru. Tempatkan kontrol Button dan empat kontrol TextBox pada halaman (menerima nama default untuk setiap kontrol).
Tambahkan kode berikut ke kelas formulir, memodifikasi string koneksi seperlunya untuk lingkungan Anda.
// Add the following using statements, if they are not already there.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;
using Microsoft.Data.SqlClient;
// Add this code to the page's class
string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
// If you have not included "Asynchronous Processing=true"
// in the connection string, the command will not be able
// to execute asynchronously.
{
return "Data Source=(local);Integrated Security=SSPI;" +
"Initial Catalog=AdventureWorks;" +
"Asynchronous Processing=true";
}
void Button1_Click(object sender, System.EventArgs e)
{
// In a real-world application, you might be connecting to
// three different servers or databases. For the example,
// we connect to only one.
SqlConnection connection1 =
new SqlConnection(GetConnectionString());
SqlConnection connection2 =
new SqlConnection(GetConnectionString());
SqlConnection connection3 =
new SqlConnection(GetConnectionString());
// To keep the example simple, all three asynchronous
// processes select a row from the same table. WAITFOR
// commands are used to emulate long-running processes
// that complete after different periods of time.
string commandText1 = "WAITFOR DELAY '0:0:01';" +
"SELECT * FROM Production.Product " +
"WHERE ProductNumber = 'BL-2036'";
string commandText2 = "WAITFOR DELAY '0:0:05';" +
"SELECT * FROM Production.Product " +
"WHERE ProductNumber = 'BL-2036'";
string commandText3 = "WAITFOR DELAY '0:0:10';" +
"SELECT * FROM Production.Product " +
"WHERE ProductNumber = 'BL-2036'";
try
// For each process, open a connection and begin
// execution. Use the IAsyncResult object returned by
// BeginExecuteReader to add a WaitHandle for the
// process to the array.
{
connection1.Open();
SqlCommand command1 =
new SqlCommand(commandText1, connection1);
IAsyncResult result1 = command1.BeginExecuteReader();
WaitHandle waitHandle1 = result1.AsyncWaitHandle;
connection2.Open();
SqlCommand command2 =
new SqlCommand(commandText2, connection2);
IAsyncResult result2 = command2.BeginExecuteReader();
WaitHandle waitHandle2 = result2.AsyncWaitHandle;
connection3.Open();
SqlCommand command3 =
new SqlCommand(commandText3, connection3);
IAsyncResult result3 = command3.BeginExecuteReader();
WaitHandle waitHandle3 = result3.AsyncWaitHandle;
WaitHandle[] waitHandles = {
waitHandle1, waitHandle2, waitHandle3
};
int index;
for (int countWaits = 0; countWaits <= 2; countWaits++)
{
// WaitAny waits for any of the processes to
// complete. The return value is either the index
// of the array element whose process just
// completed, or the WaitTimeout value.
index = WaitHandle.WaitAny(waitHandles,
60000, false);
// This example doesn't actually do anything with
// the data returned by the processes, but the
// code opens readers for each just to demonstrate
// the concept.
// Instead of using the returned data to fill the
// controls on the page, the example adds the time
// the process was completed to the corresponding
// text box.
switch (index)
{
case 0:
SqlDataReader reader1;
reader1 =
command1.EndExecuteReader(result1);
if (reader1.Read())
{
TextBox1.Text =
"Completed " +
System.DateTime.Now.ToLongTimeString();
}
reader1.Close();
break;
case 1:
SqlDataReader reader2;
reader2 =
command2.EndExecuteReader(result2);
if (reader2.Read())
{
TextBox2.Text =
"Completed " +
System.DateTime.Now.ToLongTimeString();
}
reader2.Close();
break;
case 2:
SqlDataReader reader3;
reader3 =
command3.EndExecuteReader(result3);
if (reader3.Read())
{
TextBox3.Text =
"Completed " +
System.DateTime.Now.ToLongTimeString();
}
reader3.Close();
break;
case WaitHandle.WaitTimeout:
throw new Exception("Timeout");
break;
}
}
}
catch (Exception ex)
{
TextBox4.Text = ex.ToString();
}
connection1.Close();
connection2.Close();
connection3.Close();
}
Contoh: Model tunggu (Semua)
Contoh berikut mengilustrasikan model Wait (Semua). Setelah tiga proses asinkron dimulai, metode WaitAll dipanggil untuk menunggu proses selesai atau kehabisan waktu.
Seperti contoh model Wait (Apa pun), waktu proses selesai ditambahkan ke kotak teks yang sesuai dengan proses. Sekali lagi, waktu dalam kotak teks mengilustrasikan titik : Kode yang mengikuti metode WaitAny dijalankan hanya setelah semua proses selesai.
Untuk menyiapkan contoh ini, buat proyek Situs Web ASP.NET baru. Tempatkan kontrol Button dan empat kontrol TextBox pada halaman (menerima nama default untuk setiap kontrol).
Tambahkan kode berikut ke kelas formulir, memodifikasi string koneksi seperlunya untuk lingkungan Anda.
// Add the following using statements, if they are not already there.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;
using Microsoft.Data.SqlClient;
// Add this code to the page's class
string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
// If you have not included "Asynchronous Processing=true"
// in the connection string, the command will not be able
// to execute asynchronously.
{
return "Data Source=(local);Integrated Security=SSPI;" +
"Initial Catalog=AdventureWorks;" +
"Asynchronous Processing=true";
}
void Button1_Click(object sender, System.EventArgs e)
{
// In a real-world application, you might be connecting to
// three different servers or databases. For the example,
// we connect to only one.
SqlConnection connection1 =
new SqlConnection(GetConnectionString());
SqlConnection connection2 =
new SqlConnection(GetConnectionString());
SqlConnection connection3 =
new SqlConnection(GetConnectionString());
// To keep the example simple, all three asynchronous
// processes execute UPDATE queries that result in
// no change to the data. WAITFOR
// commands are used to emulate long-running processes
// that complete after different periods of time.
string commandText1 =
"UPDATE Production.Product " +
"SET ReorderPoint = ReorderPoint + 1 " +
"WHERE ReorderPoint Is Not Null;" +
"WAITFOR DELAY '0:0:01';" +
"UPDATE Production.Product " +
"SET ReorderPoint = ReorderPoint - 1 " +
"WHERE ReorderPoint Is Not Null";
string commandText2 =
"UPDATE Production.Product " +
"SET ReorderPoint = ReorderPoint + 1 " +
"WHERE ReorderPoint Is Not Null;" +
"WAITFOR DELAY '0:0:05';" +
"UPDATE Production.Product " +
"SET ReorderPoint = ReorderPoint - 1 " +
"WHERE ReorderPoint Is Not Null";
string commandText3 =
"UPDATE Production.Product " +
"SET ReorderPoint = ReorderPoint + 1 " +
"WHERE ReorderPoint Is Not Null;" +
"WAITFOR DELAY '0:0:10';" +
"UPDATE Production.Product " +
"SET ReorderPoint = ReorderPoint - 1 " +
"WHERE ReorderPoint Is Not Null";
try
// For each process, open a connection and begin
// execution. Use the IAsyncResult object returned by
// BeginExecuteReader to add a WaitHandle for the
// process to the array.
{
connection1.Open();
SqlCommand command1 =
new SqlCommand(commandText1, connection1);
IAsyncResult result1 = command1.BeginExecuteNonQuery();
WaitHandle waitHandle1 = result1.AsyncWaitHandle;
connection2.Open();
SqlCommand command2 =
new SqlCommand(commandText2, connection2);
IAsyncResult result2 = command2.BeginExecuteNonQuery();
WaitHandle waitHandle2 = result2.AsyncWaitHandle;
connection3.Open();
SqlCommand command3 =
new SqlCommand(commandText3, connection3);
IAsyncResult result3 = command3.BeginExecuteNonQuery();
WaitHandle waitHandle3 = result3.AsyncWaitHandle;
WaitHandle[] waitHandles = {
waitHandle1, waitHandle2, waitHandle3
};
bool result;
// WaitAll waits for all of the processes to
// complete. The return value is True if the processes
// all completed successfully, False if any process
// timed out.
result = WaitHandle.WaitAll(waitHandles, 60000, false);
if(result)
{
long rowCount1 =
command1.EndExecuteNonQuery(result1);
TextBox1.Text = "Completed " +
System.DateTime.Now.ToLongTimeString();
long rowCount2 =
command2.EndExecuteNonQuery(result2);
TextBox2.Text = "Completed " +
System.DateTime.Now.ToLongTimeString();
long rowCount3 =
command3.EndExecuteNonQuery(result3);
TextBox3.Text = "Completed " +
System.DateTime.Now.ToLongTimeString();
}
else
{
throw new Exception("Timeout");
}
}
catch (Exception ex)
{
TextBox4.Text = ex.ToString();
}
connection1.Close();
connection2.Close();
connection3.Close();
}