1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Canceling an Asynchronous Query pptx

5 161 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Canceling an Asynchronous Query
Tác giả Team Lib
Trường học University of Northwind
Chuyên ngành Computer Science
Thể loại Tài liệu
Thành phố Northwind
Định dạng
Số trang 5
Dung lượng 27,85 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

[ Team LiB ]Recipe 9.2 Canceling an Asynchronous Query Problem Given a query running that runs asynchronously on a background thread, you want to give the user the option to cancel the

Trang 1

[ Team LiB ]

Recipe 9.2 Canceling an Asynchronous Query

Problem

Given a query running that runs asynchronously on a background thread, you want to give the user the option to cancel the query if it is taking too long

Solution

Abort the background thread and clean up in an exception handler

The sample code contains two event handlers and a single method:

Start Button.Click

Checks whether there is an existing background thread loading the DataSet If the DataSet is not being loaded, a new thread is created invoking the

AsyncFillDataSet( ) method to fill a DataSet Otherwise, a message is displayed stating that the DataSet is currently being filled

Cancel Button.Click

Aborts the background thread filling the DataSet

AsyncFillDataSet( )

This method loads a DataSet with the Orders and Order Details tables from the Northwind database The method displays a message when the method has started and when it has completed The method also traps the ThreadAbortException to handle the situation where the fill on the background thread is canceled

The C# code is shown in Example 9-2

Example 9-2 File: AsynchronousFillCancelForm.cs

// Namespaces, variables, and constants

using System;

using System.Configuration;

using System.Threading;

using System.Data;

using System.Data.SqlClient;

Trang 2

// Table name constants

private const String ORDERS_TABLE = "Orders";

private const String ORDERDETAILS_TABLE = "OrderDetails";

// Relation name constants

private const String ORDERS_ORDERDETAILS_RELATION = "Orders_OrderDetails_Relation";

// Field name constants

private const String ORDERID_FIELD = "OrderID";

private const String ORDERDATE_FIELD = "OrderDate";

private Thread thread;

//

private void startButton_Click(object sender, System.EventArgs e) {

// Check if a new thread can be created

if (thread == null ||

(thread.ThreadState & (ThreadState.Unstarted |

ThreadState.Background)) == 0)

{

// Create and start a new thread to fill the DataSet

thread = new Thread(new ThreadStart(AsyncFillDataSet));

thread.IsBackground = true;

thread.Start( );

}

else

{

// DataSet already being filled Display a message

statusTextBox.Text += "DataSet still filling " +

Environment.NewLine;

statusTextBox.Refresh( );

}

}

private void cancelButton_Click(object sender, System.EventArgs e) {

// Check if the thread is running and an abort has not been requested

if (thread != null &&

(thread.ThreadState &

(ThreadState.Stopped | ThreadState.Aborted |

Trang 3

ThreadState.Unstarted | ThreadState.AbortRequested)) == 0)

{

try

{

// Abort the thread

statusTextBox.Text += "Stopping thread " +

Environment.NewLine;

statusTextBox.Refresh( );

thread.Abort( );

thread.Join( );

statusTextBox.Text += "Thread stopped." +

Environment.NewLine;

}

catch (Exception ex)

{

statusTextBox.Text += ex.Message + Environment.NewLine; }

}

else

{

statusTextBox.Text += "Nothing to stop." + Environment.NewLine; }

}

private void AsyncFillDataSet( )

{

try

{

statusTextBox.Text = "Filling DataSet " +

Environment.NewLine;

statusTextBox.Refresh( );

DataSet ds = new DataSet("Source");

SqlDataAdapter da;

// Fill the Order table and add it to the DataSet

da = new SqlDataAdapter("SELECT * FROM Orders",

ConfigurationSettings.AppSettings["Sql_ConnectString"]);

DataTable orderTable = new DataTable(ORDERS_TABLE);

da.FillSchema(orderTable, SchemaType.Source);

da.Fill(orderTable);

ds.Tables.Add(orderTable);

Trang 4

// Fill the OrderDetails table and add it to the DataSet

da = new SqlDataAdapter("SELECT * FROM [Order Details]",

ConfigurationSettings.AppSettings["Sql_ConnectString"]);

DataTable orderDetailTable = new DataTable(ORDERDETAILS_TABLE);

da.FillSchema(orderDetailTable, SchemaType.Source);

da.Fill(orderDetailTable);

ds.Tables.Add(orderDetailTable);

// Create a relation between the tables

ds.Relations.Add(ORDERS_ORDERDETAILS_RELATION,

ds.Tables[ORDERS_TABLE].Columns[ORDERID_FIELD],

ds.Tables[ORDERDETAILS_TABLE].Columns[ORDERID_FIELD],

true);

statusTextBox.Text += "DataSet fill complete." +

Environment.NewLine;

}

catch (ThreadAbortException ex)

{

// Exception indicating that thread has been aborted

statusTextBox.Text += "AsyncFillDataSet( ): " + ex.Message +

Environment.NewLine;

}

}

Discussion

Recipe 9.1 discusses using a background thread to fill a DataSet to improve application

performance

The ThreadState of a thread specifies its execution state This value is a bitwise

combination of ThreadState enumeration described in Table 9-1

Table 9-1 ThreadState enumeration Value Description

Aborted The thread is stopped

AbortRequested

The Abort( ) method of the thread has been called but the thread has not yet received the ThreadAbortException that will terminate

it

Background The thread is being executed on a background thread rather than a

Trang 5

foreground thread This is specified by the IsBackground property

of the thread

Running The thread has been started, is not blocked, and there is no pending

ThreadAbortException

Stopped The thread is stopped

StopRequested The thread is being requested to stop This value is for internal use

only

Suspended The thread is suspended

SuspendRequested The thread is being requested to suspend

Unstarted The thread is not started and the Start( ) method has not been called

on the thread

WaitSleepJoin The thread is blocked by a Wait( ), Sleep( ), or Join( ) method

In the solution, a background thread is used to fill the DataSet The ThreadState of the thread object is used to determine whether it can be started or whether it can be aborted,

as follows:

• A thread can be started only if it does not have a ThreadState of Unstarted or Background

• A thread can be aborted only if its ThreadState is not Stopped, Aborted, Unstarted,

or AbortRequested

The Abort( ) method of the Thread raises a ThreadAbortException in the thread on which

it is invoked and begins the process of terminating the thread ThreadAbortException is a special exception, although it can be caught, it is automatically raised again at the end of

a catch block All finally blocks are executed before killing the thread Because the thread can do an unbounded computation in the finally blocks, the Join( ) method of the

thread—a blocking call that does not return until the thread actually stops executing—is used to guarantee that the thread has terminated Once the thread is stopped, it cannot be restarted

[ Team LiB ]

Ngày đăng: 26/01/2014, 10:20

w