问题
i am in the process implementing SQLdepenency i would like to know in case of Dependency Handler exeuctues will it spun a different thred from main Process ? What will happen when the event handler triggers? Do i need to worry about any multithreds issues?
public void CreateSqlDependency()
{
try
{
using (SqlConnection connection = (SqlConnection)DBFactory.GetDBFactoryConnection(Constants.SQL_PROVIDER_NAME))
{
SqlCommand command = (SqlCommand)DBFactory.GetCommand(Constants.SQL_PROVIDER_NAME);
command.CommandText = watchQuery;
command.CommandType = CommandType.Text;
SqlDependency dependency = new SqlDependency(command);
//Create the callback object
dependency.OnChange += new OnChangeEventHandler(this.QueueChangeNotificationHandler);
SqlDependency.Start(connectionString);
DataTable dataTable = DBFactory.ExecuteSPReDT(command);
}
}
catch (SqlException sqlExp)
{
throw sqlExp;
}
catch (Exception ex)
{
throw ex;
}
}
public void QueueChangeNotificationHandler(object caller, SqlNotificationEventArgs e)
{
if(e.Info == SqlNotificationInfo.Insert)
Fire();
}
回答1:
It works in a separate thread, but there is only one such thread for all notifications. Have a look at the SQLDependency section in this article
回答2:
SqlDependency documentation on MSDN mention about possibility that the OnChange event may be generated on a different thread from the thread that initiated command execution.
You should read Detecting Changes with SqlDependency (ADO.NET) article from MSDN which explain similar scenario.
回答3:
It will spawn a new worker thread to wait for the dependency notifications--but that's what you want (otherwise your main program loop would be held up waiting for something that may never happen!).
The example code at this page shows to how avoid issues where the worker thread that gets the dependency/query notifications doesn't have the right to update the UI; their method passes the task to the UI thread so it will succeed (see step #12).
回答4:
It does spawn in a different thread!! You can create a simple Windows Application to test this, and you'll see how the OnChange handler can't modify any UI controls directly (you'd get something like "Cross-thread operation not valid: Control XXX accessed from a thread other than the thread it was created on"). To overcome this, you call BeginInvoke.
Here's a simple Windows application to test SqlDependencies (I hope you can imagine the UI).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace TestSqlDependancies
{
public partial class SqlDependencyTester : Form
{
SqlDependency sqlDepenency = null;
SqlCommand command;
SqlNotificationEventArgs msg;
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
public delegate void InvokeDelegate();
void sqlDepenency_OnChange(object sender, SqlNotificationEventArgs e)
{
msg = e;
this.BeginInvoke(new InvokeDelegate(Notify));
}
private void Notify()
{
listBox1.Items.Add(DateTime.Now.ToString("HH:mm:ss:fff") + " - Notfication received. SqlDependency " + (sqlDepenency.HasChanges ? " has changes." : " reports no change. ") + msg.Type.ToString() + "-" + msg.Info.ToString());
}
private void button1_Click(object sender, EventArgs e)
{
SetDependency();
}
private void SetDependency()
{
try
{
using (TicketDataContext dc = new TicketDataContext())
{
SqlDependency.Start(dc.Connection.ConnectionString);
command = new SqlCommand(textBox1.Text, (SqlConnection)dc.Connection);
sqlDepenency = new SqlDependency(command);
sqlDepenency.OnChange += new OnChangeEventHandler(sqlDepenency_OnChange);
command.Connection.Open();
command.ExecuteReader();
}
}
catch (Exception e)
{
listBox1.Items.Add(DateTime.Now.ToString("HH:mm:ss:fff") + e.Message);
}
}
}
}
来源:https://stackoverflow.com/questions/2730798/sqldependency-thread