# MultiRead Sample: Reads Database Table Using Multiple Threads

The MultiRead sample demonstrates how to use the OLE DB Consumer Templates classes to read through a table in a database using multiple threads.

The MultiRead attributes sample is the attributed version of this sample.

Security Note
This sample code is provided to illustrate a concept and should not be used in applications or Web sites, as it may not illustrate the safest coding practices.

# Building and Running the Sample

#### To build and run this sample

1. Open the solution file MultiRead.sln.

2. From the Build menu, click Build.

3. From the Debug menu, click Start Without Debugging.

4. A Multi-Threaded Read dialog box will appear, prompting you to specify the number of threads to use to read through the table. Click Run.

5. The result will appear as text in the Multi-Threaded Read dialog box, for example, `15 records in 7 ms`.

# How the Sample Works

The sample contains the `CMultiDlg` class, which is used to show a dialog box. With this dialog box, the user enters the number of threads to use to read through the table. When the user clicks the Run button, `ReadRecords` in DBRead.h is called to open the database, the session, and the table, and to create the necessary number of threads. As it opens the table, the function sets the DBPROP_CANHOLDROWS property to true so that the provider allows the user to retrieve new rows without releasing the previously retrieved rows. This capability is required, because multiple threads retrieve new rows as other threads are still processing their current threads.

The sample also shows how to extend the standard CRowset class by creating a new `CMyRowset` class, which derives from CRowset, and adds the `MoveAndProcess` member function. The start routine of each thread is the `ReadTable` function, and the table class is passed to this function. The function calls the routine `MoveAndProcess` to read through each record. Note that the accessor class `CProduct` is defined so that the data will not be retrieved automatically on the `MoveNext` call. This avoids buffer conflicts with the other threads, and there is no need to protect `MoveNext` with a critical section. The `MoveAndProcess` function calls `MoveNext`, and then calls `GetDataHere` to place the data directly into a local variable of that function. `ProcessRecord` is called for each record retrieved, and the function simply traces out the values of the record by default.

Each thread counts the number of records it reads, and those are traced out at the end, along with a total and time taken, which is displayed on the dialog box.

Note
The MultiRead sample reads the MultiRead.mdb database file. The sample code assumes that this file is located in the current directory.

# Keywords

The sample demonstrates the following classes:

CAccessor, CDataSource, CDBPropSet, CRowset, CSession, CTable

The sample demonstrates the following macros:

BEGIN_ACCESSOR_MAP, BEGIN_ACCESSOR, COLUMN_ENTRY, END_ACCESSOR, END_ACCESSOR_MAP, DEFINE_COMMAND

The sample demonstrates the following functions:

CreateThread, GetCurrentThreadId, GetExitCodeThread, WaitForMultipleObjects

Note
Some of the samples, such as this one, have not been modified to reflect the changes in the Visual C++ wizards, libraries, and compiler, but still demonstrate how to complete your desired task.