У меня есть база данных, работающая на машине, которая служит для обновления информации от секунды к секунде. Все мои клиенты предоставили данные, все они возвращаются в один источник, который, в свою очередь, публикует данные в базе данных. Все это хорошо, проблема, с которой я сталкиваюсь, связана с моим сервис-брокером и прослушиванием изменений.
Я использую объект SqlDependency для регистрации слушателей для конкретных запросов. Я получаю события, как ожидалось, однако сервер в конечном итоге становится непригодным для использования. Я смог определить, что компонент Service Broker использует более 900 МБ памяти (что приводит к превышению лимита в 1 ГБ для экспресс-доставки). У меня сложилось впечатление, что мои события остаются в памяти и не очищаются. Каждый раз, когда я получаю событие, я очищаю этого слушателя события и регистрирую нового. Есть ли более правильный способ удалить это событие из базы данных?
Кроме того, я прочитал все, что вы должны вызывать Stop и Start каждый раз, когда вы регистрируете новое событие. По моему опыту, вызов Stop во второй раз всегда зависает навсегда. Кроме того, если остановка удаляет все события, у меня есть несколько слушателей, и я не хочу останавливать другие, когда получаю одно.
Вот код, который я использую для регистрации и ответа на события:
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.DatabseEventConnectionString))
{
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT Field1, Field2, Field3, Field4 FROM dbo.Table";
cmd.Notification = null;
SqlDependency dep = new SqlDependency(cmd);
dep.OnChange += new OnChangeEventHandler(dependency_OnChange);
cn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle read here;
}
}
}
void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
// If InvokeRequired returns True, the code
// is executing on a worker thread.
if (Dispatcher.CheckAccess())
{
SqlDependency dep = sender as SqlDependency;
dep.OnChange -= new OnChangeEventHandler(dependency_OnChange);
RegisterTableListener();
}
else
{
// Create a delegate to perform the thread switch.
OnChangeEventHandler tempDelegate =
new OnChangeEventHandler(dependency_OnChange);
object[] args = { sender, e };
// Marshal the data from the worker thread
// to the UI thread.
Dispatcher.Invoke(tempDelegate, args);
}
}
Есть идеи, почему память вечно взбирается?