3

私は SQLdepenency を実装するプロセスにいます。依存関係ハンドラーが実行された場合に知りたいのですが、メインのプロセスとは異なるスレッドがスピンされますか? イベント ハンドラーがトリガーされるとどうなりますか? マルチスレッドの問題について心配する必要はありますか?

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();
}
4

4 に答える 4

2

これは別のスレッドで機能しますが、すべての通知に対してそのようなスレッドは 1 つしかありません。この記事の SQLDependency セクションをご覧ください。

于 2010-12-14T09:44:56.873 に答える
0

別のスレッドでスポーンします!! これをテストする単純な Windows アプリケーションを作成すると、OnChange ハンドラーが UI コントロールを直接変更できないことがわかります (「クロススレッド操作が無効です: コントロール XXX がスレッドからアクセスされました」などのメッセージが表示されます)。作成されたスレッドよりも")。これを克服するには、BeginInvoke を呼び出します。

SqlDependencies をテストする単純な Windows アプリケーションを次に示します (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);
            }
        }
    }
}
于 2010-11-05T17:28:33.607 に答える
0

MSDN のSqlDependencyドキュメントでは、コマンドの実行を開始したスレッドとは異なるスレッドで OnChange イベントが生成される可能性について言及しています。

同様のシナリオを説明する MSDNの SqlDependency による変更の検出 (ADO.NET)の記事を読む必要があります。

于 2010-04-28T15:30:51.130 に答える
0

依存関係の通知を待つために新しいワーカースレッドを生成しますが、それはあなたが望むものです(そうでなければ、あなたのメインプログラムループは決して起こらないかもしれない何かを待って停止します!)。

このページのコード例は、依存関係/クエリ通知を受け取るワーカー スレッドが UI を更新する権限を持たない問題を回避する方法を示しています。それらのメソッドはタスクを UI スレッドに渡し、タスクが成功するようにします (手順 12 を参照)。

于 2010-04-28T19:46:00.563 に答える