2009-01-30 4 views
4

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

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

Ниже, как я в настоящее время настроить каждую нить:

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

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

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

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

+1

Кто знает? Вы сделали это явно. Просто, когда я начинаю думать, что у меня есть рудиментарное знание языка, появляется какой-то парень и говорит, что вы знаете, что вам не нужно тащить это ... у нас здесь колеса! Благодаря! - Брэд (1 мин. Назад) – Brad

1

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

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

+0

Кто знал? Вы сделали это явно. Просто, когда я начинаю думать, что у меня есть рудиментарное знание языка, появляется какой-то парень и говорит, что вы знаете, что вам не нужно тащить это ... у нас здесь колеса! Благодаря! – Brad

2

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

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

4

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

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

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

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

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

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

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

+0

, что я получу, заключается в том, что пользователь может начать интерпретировать сгенерированные графики из того, какая информация была возвращена. Некоторые запросы возвращаются через несколько секунд, другие согласуются на 90 секунд. – Brad

+0

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

+0

Извините, не могу помочь вам ... – mghie

0

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

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

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

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

Смежные вопросы