Многопоточные приложения в Delphi

  • Вид работы:
    Курсовая работа (т)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    581,32 Кб
  • Опубликовано:
    2013-09-20
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Многопоточные приложения в Delphi

Министерство образования республики Беларусь

Учреждение образования

«Гомельский государственный университет имени Франциска Скорины»

Математический факультет

Кафедра ВМиП

 






Курсовая работа

Многопоточные приложения в Delphi











Гомель, 2012

Введение

Потоки появились еще в Windows NT, но до определенного времени редко использовались прикладными программистами. В наше время эта тема очень актуальна, когда даже самый захудалый офисный компьютер обладает как минимум двумя процессорными ядрами, не использовать потоки в программах просто неприлично. Например, всё программирование звука написано с использованием потоков, или параллельная проверка орфографии в Microsoft Word.

Целью моей курсовой работы было разработать оконное многопоточное приложение, которое будет выполнять SQL-запросы базы данных, используя несколько потоков, что существенно увеличивает продуктивность программы, что в свою очередь уменьшает время ожидания пользователя.

В первом разделе отчета по моей курсовой работы приведена информация о многопоточности и о типах реализации потоков, во втором разделе была рассмотрена проблема взаимодействия потоков с общими ресурсами, а так же способы решения данных проблем. Классы реализации многопоточности в Delphi, были приведены в третьем пункте, вместе с разработанным мною наследником класса TThread, который является одним из способов реализации потоков в Delphi. В четвертой части представлен интерфейс взаимодействия пользователя с приложением, а так же был приведён пример работы мною разработанного многопоточного приложения.

1. Понятие многопоточности

Параллельное программирование возникло в 1962 г. с изобретением каналов - независимых аппаратных контролеров, позволяющих центральному процессору выполнять новую прикладную программу одновременно с операциями ввода-вывода других (приостановленных) программ. Параллельное программирование (слово параллельное в данном случае обозначает «происходящее одновременно») первоначально было уделом работников операционных систем. В конце 60-х годов были созданы многопроцессорные машины. В результате не только были поставлены новые задачи разработчикам операционных систем, но и появились новые возможности у прикладных программистов.

Всем известно, что Windows система многозадачная. Попросту говоря, это означает, что несколько программ могут работать одновременно под управлением оперативной системы. Все мы открывали диспетчер задач и видели список процессов. Процесс - это экземпляр выполняемого приложения. На самом деле сам по себе он ничего не выполняет, он создаётся при запуске приложения, содержит в себе служебную информацию, через которую система с ним работает, так же ему выделяется необходимая память под код и данные. Для того, чтобы программа заработала, в нём создаётся поток. Любой процесс содержит в себе хотя бы один поток, и именно он отвечает за выполнение кода и получает на это процессорное время. Этим и достигается мнимая параллельность работы программ, или, как её еще называют, псевдопараллельность. Почему мнимая? Да потому, что реально процессор в каждый момент времени может выполнять только один участок кода. Windows раздаёт процессорное время всем потокам в системе по очереди, тем самым создаётся впечатление, что они работают одновременно. Реально работающие параллельно потоки могут быть только на машинах с двумя и более процессорами.

Многопоточность это свойство платформы или приложения (например, операционной системы или виртуальной машины), состоящее в том, что процесс, порождённый в операционной системе, может состоять из нескольких потоков, выполняющихся «параллельно», то есть без предписанного порядка во времени. При выполнении некоторых задач такое разделение может достичь более эффективного использования ресурсов вычислительной машины.

Любая программа содержит хотя бы один поток (главный), в котором она выполняется. Помимо этого, она может порождать любое количество дополнительных потоков, которые будут выполняться в фоновом режиме. У дополнительных потоков приоритет выстраивается такой же, как и у главного потока программы, но программист может увеличить его или уменьшить. Чем выше приоритет потока, тем больше на него отводится процессорного времени.

Сутью многопоточности является квазимногозадачность на уровне одного исполняемого процесса, то есть все потоки выполняются в адресном пространстве процесса. Кроме этого, все потоки процесса имеют не только общее адресное пространство, но и общие дескрипторы файлов.

Время работы процессора разбивается на небольшие интервалы, обычно называемые квантами. Когда квант времени заканчивается, выполнение текущего потока приостанавливается, содержимое регистров процессора сохраняется в специальной области памяти, и он переключается на обработку следующего потока. Когда очередь снова дойдет до этого потока, содержимое регистров будет полностью восстановлено и работа потока продолжится так, как будто она вовсе и не прерывалась. Таким образом, переключение потоков происходит совершенно незаметно для них самих.

К достоинствам многопоточности в программировании можно отнести следующее:

         Упрощение программы в некоторых случаях, за счет использования общего адресного пространства;

         Меньшие относительно процесса временные затраты на создание потока;

         Повышение производительности процесса за счет распараллеливания процессорных вычислений и операций ввода/вывода.

.1 Типы реализации потоков

Каждый процесс имеет таблицу потоков, аналогичную таблице процессов ядра. Достоинства и недостатки этого типа следующие:

Достоинства:

         возможность реализации на ядре не поддерживающем многопоточность;

         Более быстрое переключение, создание и завершение потоков;

         процесс может иметь собственный алгоритм планирования.

Недостатки:

         Отсутствие прерывания по таймеру внутри одного процесса;

         При использовании блокирующего системного запроса все остальные потоки блокируются;

         Сложность реализации.

Смешанная реализация. Потоки работают в режиме пользователя, но при системных вызовах переключаются в режим ядра. Переключение в режим ядра и обратно является ресурсоемкой операцией и отрицательно сказывается на производительности системы. Поэтому было введено понятие волокна - облегченного потока, выполняемого исключительно в режиме пользователя.

Создать дополнительный поток в Delphi поможет объект TThread. Ввести объект TThread в программу можно двумя способами:

         с помощью Мастера;

         вручную.

Мастер создания дополнительного потока в Delphi создаёт отдельный модуль, в рамках которого выполняется поток. Выполним:-> New -> Other...

В появившейся табличке выбора найдём TThread Object. Появится окошко, в верхнюю строку которого (Class Name) введём имя нашего будущего потока: MyThread. В результате будет создан модуль, содержащий заготовку кода, реализующего дополнительный поток Delphi. Если поток создаётся мастером, т.е. в другом модуле, то не забудьте в основном модуле описать переменную - экземпляр потока. Также, поскольку класс потока описан в другом модуле, имя этого модуля необходимо добавить в секцию uses.

В первом способе класс MyThread был создан мастером в дополнительном модуле. Второй способ состоит в том, что мы сами создаём такой класс в рамках одного из уже существующих модулей программы, например, в модуле Unit1.

. Взаимодействие протоков и их общее ресурсы

В процессе разработки многопоточного приложения приходится решать две взаимосвязанные проблемы - разграничение доступа к ресурсам и взаимоблокировки. Если несколько потоков обращаются к одному и тому же ресурсу (области памяти, файлу, устройству) при небрежном программировании может возникнуть ситуация, когда сразу несколько потоков попытаются выполнить некие манипуляции с общим ресурсом. При этом нормальная последовательность операций при обращении к ресурсу, скорее всего, будет нарушена. Проблема с разграничением доступа может возникнуть даже при очень простых операциях. Предположим, у нас есть программа, которая создает несколько потоков. Каждый поток выполняет свою задачу, и затем завершается. Мы хотим контролировать количество потоков, активных в данное время, и с этой целью вводим счетчик потоков - глобальную переменную Counter. Процедура потока при этом может выглядеть так:

procedure MyThread.Execute;

begin(Counter);

...(Counter);;

Одна из проблем, связанных с этим кодом заключается в том, что процедуры Inc и Dec не атомарные (например, процедуре Inc требуется выполнить три инструкции процессора - загрузить значение Counter в регистр процессора, выполнить сам инкремент, затем записать результат из регистра процессора в область памяти Counter). Нетрудно догадаться, что если два потока попытаются выполнить процедуру Inc одновременно, значение Counter может быть увеличено на 1 вместо 2.

В общем случае для решения проблемы разделения доступа используются блокировки - специальные механизмы, которые гарантируют, что в каждый данный момент времени только один поток имеет доступ к некоторому ресурсу. В то время, когда ресурс заблокирован одним потоком, выполнение других потоков, пытающихся получить доступ к ресурсу, приостанавливается. Однако использование блокировок создает другую проблему - взаимоблокировки (deadlocks). Взаимоблокировка наступает тогда, когда потока A блокирует ресурс, необходимый для продолжения работы потока B, а поток B блокирует ресурс, необходимый для продолжения работы потока A. Поскольку ни один поток не может продолжить выполнение, заблокированные ресурсы не могут быть разблокированы, что приводит к повисанию потоков.

.1 Решение проблем с общими ресурсами

При выполнении нескольких потоков существует вероятность того, что они будут взаимодействовать друг с другом. Для того чтобы синхронизировать свое выполнение и существует несколько методов синхронизации потоков:

-             Блоки взаимного исключения (Mutex);

-             Переменные состояния;

-             Семафоры.

Объекты синхронизации являются переменными в памяти, к которым можно обратиться так же, как к данным. Потоки в различных процессах могут связаться друг с другом через объекты синхронизации, помещенные в разделяемую память потоков, даже в случае, когда потоки в различных процессах вообще невидимы друг для друга.

Объекты синхронизации можно разместить в файлах, где они будут существовать независимо от создавшего их процесса.

Основные ситуации, которые требуют использования синхронизации:

-             Если синхронизация - это единственный способ гарантировать последовательность разделяемых данных;

-             Если потоки в двух или более процессах могут использовать единственный объект синхронизации совместно. При этом объект синхронизации должен инициализироваться только одним из взаимодействующих процессов, потому что повторная инициализация объекта синхронизации устанавливает его в открытое состояние;

-             Если процесс может отобразить файл и существует поток в этом процессе, который получает уникальный доступ к записям. Как только установлена блокировка, любой другой поток в любом процессе, отображающем файл, который пытается установить блокировку, блокируется, пока запись не будет освобождена.

Блоки взаимного исключения (Mutex) - это объект синхронизации, который устанавливается в особое сигнальное состояние, когда не занят каким-либо потоком. Только один поток владеет этим объектом в любой момент времени, отсюда и название таких объектов (от английского mutually exclusive access - взаимно исключающий доступ) - одновременный доступ к общему ресурсу исключается. После всех необходимых действий мьютекс освобождается, предоставляя другим потокам доступ к общему ресурсу. Объект может поддерживать рекурсивный захват второй раз тем же потоком, увеличивая счетчик, не блокируя поток, и требуя потом многократного освобождения.

Семафоры представляют собой доступные ресурсы, которые могут быть приобретены несколькими потоками в одно и то же время, пока пул ресурсов не опустеет. Тогда дополнительные потоки должны ждать, пока требуемое количество ресурсов не будет снова доступно. Семафоры очень эффективны, поскольку они позволяют одновременный доступ к ресурсам. Семафор есть логическое расширение мьютекса - семафор со счетчиком 1 эквивалентен мьютексу, но счетчик может быть и более 1.

.2 Критические секции

Наиболее простым в понимании является TCriticalSection или критическая секция. Код, расположенный в критической секции, может выполняться только одним потоком. В принципе код ни как не выделяется, а происходит обращение к коду через критическую секцию. В начале кода находится функция входа в секцию, а по завершению его выход из секции. Если секция занята другим потоком, то потоки ждут, пока критическая секция не освободится.

Рисунок 2.1.2.1 - Схема критической секции

В начале работы критическую секцию необходимо создать:

var: TCriticalSection; // глобальная переменная

section.create;;

После этого, в необходимых местах кода, нужно установить вход и выход критической секции соответственно, section.enter и section.leave. Критических секций может быть несколько. Поэтому при использовании нескольких функций, в которых могут быть конфликты по данным надо для каждой функции создавать свою критическую секцию. После окончания их использования, когда функции больше не будут вызываться, секции необходимо уничтожить подобным образом section.free.

3. Классы и процедуры реализации многопоточности в Delphi

С точки зрения операционной системы поток - это ее объект. При создании он получает дескриптор и отслеживается ОС. Объект класса TThread - это конструкция Delphi, соответствующая потоку. Этот объект создается до реального возникновения потока в системе и уничтожается после его исчезновения. Другая отличительная черта класса TThread - это совместимость с библиотекой визуальных компонентов VCL.

Класс TThread включает в себя следующие элементы:

1.      Constructor Create (Create Suspended: Boolean). В качестве аргумента он получает параметр CreateSuspended. Если его значение равно True, вновь созданный поток не начинает выполняться до тех пор, пока не будет сделан вызов метода Resume. В случае, если CreateSuspended имеет значение False, поток начинает исполнение и конструктор завершается;

.        Destructor Destroy; override. Деструктор Destroy вызывается, когда необходимость в созданном потоке отпадает. Деструктор завершает его и высвобождает все ресурсы, связанные с объектом TThread;

.        Procedure Resume. Метод Resume класса TThread вызывается, когда поток возобновляется после остановки, или если он был создан с параметром create Suspended, равным True;

.        Procedure Suspend. Вызов метода Suspend приостанавливает поток с возможностью повторного запуска впоследствии. Метод Suspend приостанавливает поток вне зависимости от кода, исполняемого потоком в данный момент; выполнение продолжается с точки останова;

.        Property Suspended: Boolean. Свойство Suspended позволяет программисту определить, не приостановлен ли поток. С помощью этого свойства можно также запускать и останавливать поток. Установив suspended в True, будет получен тот же результат, что и при вызове метода Suspend - приостановку. Наоборот, установка Suspended в False возобновляет выполнение потока, как и вызов метода Resume;

.        Function WaitFor: Integer. Метод WaitFor предназначен для синхронизации потоков и позволяет одному потоку дождаться момента, когда завершится другой поток. Если внутри потока FirstThread имеется код::= SecondThread.WaitFor;

то это означает, что поток FirstThread останавливается до момента завершения потока SecondThread. Метод WaitFor возвращает код завершения ожидаемого потока;

.        Property Priority: TThreadPriority. Свойство Priority позволяет запросить и установить приоритет потоков. Приоритет определяет, насколько часто поток получает время процессора. Допустимыми значениями приоритета являются tpIdie, tpLowest, tpLower, tpNormal, tpHigher, tpHighest и tpTimeCritical; delphi многопоточность программирование класс

.        Procedure Synchronize (Method: TThreadMethod). Этот метод относится к секции protected, то есть может быть вызван только из потомков TThread. Delphi предоставляет программисту метод synchronize для безопасного вызова методов VCL внутри потоков. Метод synchronize дает гарантию, что к каждому объекту VCL одновременно имеет доступ только один поток. Аргумент, передаваемый в метод synchronize, - это имя метода, который производит обращение к VCL;

.        Procedure Execute; virtual; abstract. Эта процедура является главным методом объекта TThread. В теле метода должен содержаться код, который представляет собой программу потока. Метод Execute класса TThread объявлен как абстрактный;

.        Property ReturnValue: Integer. Свойство ReturnValue позволяет узнать и установить значение, возвращаемое потоком по его завершении. Эта величина полностью определяется пользователем. По умолчанию поток возвращает ноль, но если программист захочет вернуть другую величину, то простое изменение свойства ReturnValue внутри потока позволит получить эту информацию другим потокам. Это, например, может пригодиться, если внутри потока в ходе его выполнения возникла какая-либо сложная ситуация.

.1 Разработанный наследник класса TThread

Был разработан наследник стандартного класса TThread под названием TMyThread:

type= class(TThread)Create;WorkSQL(str: string; Query: TADOQuery);Execute(); override;;

В нем была добавлена новая процедура WorkSQL (str: string; Query: TADOQuery), в которую передается строковый параметр str, отвечающий за искомое наименование товара в базе данных, а так же параметр Query типа TADOQuery, который собственно и будет выполнять запрос в бузу данных.

Так же был перегружена процедура Execute родительского класса:

procedure TMyThread.Execute;:TADOQuery;: integer;ListString do:=DM2.CreateSQL;not full do.Enter;:=GetIndex;.Leave;j<>-1 then(names[j],Query);Query.FieldByName('name').AsString<>'' then.Add(names[j]).Add(names[j]);.sGauge1.Progress:=Form1.sGauge1.Progress+1;;;.Free;;;

В процедуре создаётся объект класс TADOQuery с помощью функции CreateSQL принадлежащая написанному мною объекту класса TDataModule, которая возвращает указатель на созданный внутри этой функции объект класса TADOQuery.

function TDM2.CreateSQL():TADOQuery;:TADOQuery;:=TADOQuery.Create(DM2);.Connection:= ADOConnection1;:=Query;;

Данная функция создает объект класса TADOQuery и с помощью ранее настроенного компонента TADOConnection устанавливает связь только что созданного объект класса TADOQuery с базой данных.

Процедура Execute проверяет, есть ли ещё непроверенные записи в списке объекта класса TListString.

type= class: array of string;: TListString;: TListString;: integer;: integer;: boolean;Add(name: string);Create(fileName: string);Create1;Destroy;GetIndex():integer;

end;

Список записей объекта класса TListString формируется при создании объекта данного класса с помощью конструктора Create, в который передаётся файл, который был выбран пользователь при помощи диалогового окна. Так же в данном конструкторе вызывается конструктор Create1, для создания двух объектов этого же класса TListString, в которых будут создаваться списки с имеющимися и отсутствующими в базе данных записями.

В случае, если в списке записей имеются те, которые ещё не были проверены, то поток берёт следующую запись из списка записей с помощью функции GetIndex объекта класса TListString и проверяет на наличие наименования данного товара в базе данных, вызывая процедуру WorkSQL. В зависимости от результата запроса проверяемое значение заносится либо в список с имеющимися либо в список с отсутствующими наименованиями товара. Так же после проверки очередного значения из списка поток увеличивает полосу прогресса. После того как все записи из списка значений будут проверены, поток очистит используемый внутри данного класса объект класса TADOQuery.

function TListString.GetIndex():integer;index<count then:=index;(index);else:=-1;:=true;

end;;

Функция GetIndex в зависимости от того, существует ли ещё непроверенные записи, возвращает номер следующей свободной записи и помечает его как уже проверенный, тем самым гарантирует уникальность возвращаемого номера, то есть обеспечивает, что каждый номер из списка будет возвращён только единожды.

4. Созданное приложение

.1 Интерфейс взаимодействия программы с пользователем

Для того чтобы немного разнообразить интерфейс взаимодействия программы с пользователем мною была использована посторонняя библиотека компонентов AlphaSkin, которая позволяет изменять внешний вид стандартных компонентов, делая их более красочными. При запуске приложения перед пользователем открывается главное окно (рисунок 4.1.1).

Рисунок 4.1.1 - Главное окно приложения

Пользователю предоставлена возможность выбора желаемого количества потоков при помощи объекта класса TSpinEdit (рисунок 4.1.2).

Рисунок 4.1.2 - Выбор количества потоков

Так же пользователю предоставлена возможность выбора внешнего вида, в частности главного окна, приложения на свой вкус. Для этой цели был использован компонента, объекта класса TComboBox, в выпадающем списке которого находится перечень доступных стилей внешнего оформления приложения (рисунок 4.1.3).

Рисунок 4.1.3 - Выбор внешнего вида приложения

Для того чтобы пользователь мог указать исходный файл с наименованиями товаров, которые нужно проверить на наличие в базе данных, пользователю необходимо нажать на кнопку «Указать источник данных», после чего откроется диалоговое окно объекта класса TOpenDialog, где пользователь может выбрать искомый файл (рисунок 4.1.4).

Рисунок 4.1.4 - Диалоговое окно для выбора файла

После чего пользователь должен нажать на кнопку «Запустить», для того чтобы программа начала проверку выбранного пользователем файла. После окончания проверки программа выдаст сообщение о том, что проверка успешна завершена, что свидетельствует о том, что были созданы два файла «good» и «bad» (рисунок 4.1.5).

Рисунок 4.1.5 - Сообщение об окончании работы программы

В случае когда пользователь попытается завершить работу приложения, в то время когда программа ещё будет выполнять проверку, пользователь уведет соответствующие сообщения, в котором будет предоставлен выбор отменить закрытие приложения либо закрыть его принудительно не дожидаясь окончания проверки (рисунок 4.1.6).

Рисунок 4.1.6 - Предупреждение о несвоевременном закрытии

.2 Исходный код приложения

За время выполнения курсовой работы был разработан следующий код программы:

unit Unit1;, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, StdCtrls, ComCtrls, ExtCtrls, sPanel, sDialogs, sSkinManager,, sButton, sGauge, sLabel, sEdit, sSpinEdit, sGroupBox, acMagn,, Mask, sMaskEdit, sCustomComboEdit, sTooledit, Buttons,, sColorSelect, sComboBox, sFontCtrls, sBitBtn, ToolWin,, SyncObjs, DM, ADODB;= class: array of string;: TListString;: TListString;: integer;: integer;: boolean;Add(name: string);Create(fileName: string);Create1;Destroy;GetIndex():integer;;= class(TThread)Create;WorkSQL(str: string; Query: TADOQuery);Execute(); override;;= class(TForm): TsSkinManager;: TsSpinEdit;: TsPanel;: TsGauge;: TsButton;: TsButton;: TsLabelFX;: TsComboBox;: TsLabel;: TsBitBtn;: TsOpenDialog;bOpenClick(Sender: TObject);bStartClick(Sender: TObject);sBitBtn1Click(Sender: TObject);StyleChange(Sender: TObject);sGauge1Change(Sender: TObject);WriteFile;FormShow(Sender: TObject);FormClose(Sender: TObject; var Action: TCloseAction);

{ Private declarations }Progres;;: TForm1;: TCriticalSection;: TListString;

{$R *.dfm}TForm1.bOpenClick(Sender: TObject);OpenDialog1.Execute then:=TListString.Create(OpenDialog1.FileName);.MaxValue:=ListString.count;.SetFocus;;;TForm1.bStartClick(Sender: TObject);: integer;.Enabled:=false;:=TCriticalSection.Create;.full:=false;i:=1 to StrToInt(thCount.Text) do.Create;;TForm1.sBitBtn1Click(Sender: TObject);(bStart.Enabled=false) and (sGauge1.Progress<>sGauge1.MaxValue) thenMessagebox(Form1.Handle, 'Процесс будет остановлен, хотите продолжить','Предупреждение',36)=6 then;else;;TForm1.StyleChange(Sender: TObject);.SkinName:=Style.Text;

// Afterburner, BlueIce, Deep, KaraKum, TheFrog, UnderWater, Wood, WOT.;TForm1.WriteFile;: integer;: TextFile;(f,'good.txt');(f);i:=0 to ListString.good.count-1 do(f,ListString.good.names[i]);(f);(f,'bad.txt');(f);i:=0 to ListString.bad.count-1 do(f,ListString.bad.names[i]);(f);;TForm1.sGauge1Change(Sender: TObject);sGauge1.Progress=sGauge1.MaxValue then;('Программа успешно завершена',mtInformation,[mbOK],0);;;TForm1.FormShow(Sender: TObject);.SetFocus;;TListString.GetIndex():integer;index<count then:=index;(index);else:=-1;:=true;;;TListString.Add(name: string);(count);(names,count);[count-1]:=name;;TListString.Create1;:=0;:=0;;TListString.Create(fileName: string);: TextFile;: string;:= TListString.Create1;:= TListString.Create1;:=0;:=0;(f,fileName);(f);(f,a);(a<>'') do(a);(f,a);;(f);;TListString.Destroy;:=nil;.Free;.Free;;TMyThread.Create;Create(false);;TMyThread.WorkSQL(str: string; Query: TADOQuery);.SQL.Text:='SELECT name FROM list WHERE name='''+str+'''';.Active:=true;.ExecSQL;;TForm1.Progres;.Progress:=sGauge1.Progress+1;;TMyThread.Execute;:TADOQuery;: integer;ListString do:=DM2.CreateSQL;not full do.Enter;:=GetIndex;.Leave;j<>-1 then(names[j],Query);Query.FieldByName('name').AsString<>'' then.Add(names[j]).Add(names[j]);(Form1.Progres);;;.Free;;;TForm1.FormClose(Sender: TObject; var Action: TCloseAction);.Free;.Free;;.DM;, Classes, DB, DBTables, ADODB, Dialogs;= class(TDataModule): TADOConnection;: TADOQuery;: TDataSource;

{ Private declarations }CreateSQL():TADOQuery;;: TDM2;

{$R *.dfm}TDM2.CreateSQL():TADOQuery;:TADOQuery;:=TADOQuery.Create(DM2);.Connection:= ADOConnection1;:=Query;

end;.

4.3 Пример использования программы

В базе данных имеется набор наименований мобильных устройств сотовой связи (рисунок 4.2.1).

Рисунок 4.2.1 - Список наименования товаров

К примеру, нам нужно проверить некоторые наименования товаров на наличие их в азе данных, список которых находится в файле Audit.txt (рисунок 4.2.2).

Рисунок 4.2.2 - Содержимое файла Audit.txt

В первом случае мы выполним проверку используя один поток, во втором случае мы изменим значение количество потоков на большее чем в первом случае, к примеру, будем использовать три потока. В итоге во втором случае программа предъявила нам результаты (рисунки 4.2.3 - 4.2.4) намного раньше, чем в первом случае, тем самым значительно уменьшив ожидание пользователя.

Рисунок 4.2.3 - Содержимое файла с не имеющимися значениями

Заключение

За время выполнения курсовой работы были выполнены все поставленные задачи, то есть было спроектировано и разработано оконное многопоточное приложение с использованием SQL запросов для проверки текстового файла на имеющийся либо отсутствующий товар в базе данных. Так же были изучены методы создания и синхронизации потоков для того, чтобы уменьшить время ожидания пользователя и разрешить проблемы с взаимодействием потоков и их доступом к общим ресурсам, для правильной работы приложения.

В результате проделанной работы была создана программа, которая при помощи нескольких потоков обрабатывает заданную информацию и формирует два текстовых файла, в которых хранятся списки с имеющимися и отсутствующими наименованиями товара в базе данных.

Список использованных источников

1. Эндрюс Р. Основы многопоточного, параллельного и распределённого программирования / Р. Эндрюс. - М.: Вильмс. - 512с.: ил.

2. Тейксейра, С. Delphi 5. Руководство разработчика: учеб. пособие в 2 т. / С. Тейксейра, К. Пачеко - М.: Издательский дом «Вильямс», 2000. - Том 2. Разработка компонентов и программирование баз данных. - 992 с.

. Шкрыль, А. Разработка клиент-серверных приложений в Delphi. - СПб: БХВ-Петербург, 2006 - 480 с.

4. Ревнч Ю. В. Нестандартные приёмы программирования на Delphi. - СПб.: БХВ-Петербург, 2005. - 560 с: ил.


Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!