C # Я правильно обрабатывать несколько потоков - PullRequest
4 голосов
/ 30 января 2009

У меня есть приложение winform, которое создает 5 потоков для подключения и извлечения информации из базы данных при очень медленном соединении (90 секунд для некоторых запросов). Каждый поток имеет свой собственный экземпляр класса для выполнения SQL-запросов. Когда запрашиваемые данные получены, основной поток уведомляется событием, запущенным из класса, выполняющего запрос. После получения события обновляются различные компоненты основного потока, такие как элементы отображения или просто данные, содержащие данные для последующего использования. Запросы повторяются с различными интервалами в зависимости от типа запрашиваемой информации.

Все отлично работает ... но я не счастлив. Я чувствую, что это должно быть сделано по-другому, но я не уверен, каким образом.

Ниже показано, как я сейчас настраиваю каждый поток:

string ConnectionString = @"Data Source=mySrv;Initial Catalog=myTbl;Connect Timeout=30;UID=sa;pwd=mypwd";


//thread #1    
 SQL_Requests ReasonRequests;
 Thread Reason_Thread;
 ReasonRequests = new SQL_Requests();
 ReasonRequests.ProcessFinished += new SQL_Requests.ProcessFinished(ReasonRequests_Completed);
 Reason_Thread = new Thread(ReasonRequests.ExecuteQuery);
 ReasonRequests.DBQueryString = "select * from ReasonTable where staralingment = goodalignment"
 ReasonRequests.DBConnection = ConnectionString;

//thread #2
SQL_Requests EventRequests; 
Thread Event_Thread;
EventRequests = new SQL_Requests();
EventRequests.ProcessFinished += new SQL_Requests.ProcessFinished(EventRequests_Completed);
Event_Thread= new Thread(EventRequests.ExecuteQuery);

EventRequests.DBQueryString = "select * from EventTable where somefield = somevalue"
EventRequests.DBConnection = ConnectionString;

каждый Thread.start находится на разных интервалах.

какие-нибудь рекомендации?

Ответы [ 5 ]

5 голосов
/ 30 января 2009

Вместо того, чтобы раскручивать свои собственные потоки, вы должны выглядеть как асинхронные методы для выполнения запросов, т.е. http://msdn.microsoft.com/en-ca/library/system.data.sqlclient.sqlcommand.beginexecutereader.aspx

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

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

4 голосов
/ 30 января 2009

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

OTOH может быть лучше использовать один поток для всех операций извлечения данных:

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

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

ИМХО, вы должны хранить выборки в потоке для лучшей отзывчивости интерфейса, но используйте только один.

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

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

2 голосов
/ 30 января 2009

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

Если бы при параллельной обработке имелось преимущество в производительности, я бы использовал встроенный пул потоков (System.Threading.ThreadPool.QueueUserWorkItem). Если вам не требуется больше контроля над потоками, пул потоков идеально подходит для операций типа «запусти и забудь». Вы ставите в очередь операцию, и она вызывает делегата, когда она завершена.

1 голос
/ 30 января 2009

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

Честно говоря, если бы я искал "другой способ" сделать это, я бы, вероятно, пропустил многопоточный доступ к базе данных, имел бы один поток, выполняющий всю работу с базой данных, с рабочими потоками, выполняющими любые дополнительные работа, которая должна произойти (если есть), а затем отправка отчета в основной поток для доступа к БД.

0 голосов
/ 23 марта 2009

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

Пожалуйста, прочитайте следующие статьи: http://blog.rednael.com/2009/02/05/ParallelProgrammingUsingTheParallelFramework.aspx http://blog.rednael.com/2009/03/16/ParallelFrameworkDownloadAndSupport.aspx

Это статьи о базовом параллельном программировании, а также ссылки на другие статьи об истории параллелизма. Включены примеры в C # .Net. Также описывается облегченная параллельная структура для работы с задачами. В отличие от некоторых других фреймворков, этот очень легкий и очень простой в использовании. Прочитав эти статьи, вы сможете писать код, используя параллелизм.

С уважением, Мартейн

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...