1

SqlDependency を使用して SQL データベースの変更を待機する SqlListener クラスを実装しました。ビジネス ワークフローのある時点で、データベースにレコードが表示されるのを待つ必要があります。SqlListener は、要求されたレコードが見つかったときにイベントをトリガーします。これはうまくいきます。While ループに入り、イベントが返されるのを検出するまで待機することで機能させることができます。しかし、これは理想的な設計ではありません。それはプロセッサを無駄に回転させます。

もっと賢く開催を待ちたいと思います。Task、NotificationDelegate、ManualResetEvent などの使用に関する多くの提案を読みましたが、すべてをまとめることはできませんでした。

単純化された例は、おそらく理解を容易にするでしょう。これが私の現在のセットアップです。しかし、可能であれば、い while ループを取り除きたいです。

private const int MaxWaitTime = 5;
private SqlListener<RecordType> _recordListener;
private RecordType _record;

/// <summary>
/// Request a record and wait until it is found.
/// </summary>
public RecordType GetRecordAwait(int requestedId)
{
    // Initiate listening for record
    _recordListener = new SqlListener<RecordType>();
    _recordListener.SqlModified += SqlListener_SqlModified;
    _recordListener.StartListening(requestedId);

    // Wait until record is found
    var startTime = DateTime.Now;
    while (_record == null && 
                 DateTime.Now.Subtract(startTime).TotalSeconds < MaxWaitTime)
    {
        Thread.Sleep(1);
    }
    // Stop listening
    _recordListener.SqlModified -= SqlListener_SqlModified;
    _recordListener.Dispose();
    _recordListener = null;

    // Return record
    return _record;
}

private void SqlListener_SqlModified(object sender, SqlModifiedArgs args)
{
    _record = (RecordType)args.Record;
}
4

2 に答える 2

0

実際、解決策は私が最初に考えたよりも簡単でした。質問を言い換えて、もう一度検索したところ、見つかりました。私の質問ですでに述べた ManualResetEvent は、それを解決する最も簡単な方法であることが判明しました。

私がしなければならなかったのは、ManualResetEvent を追加して、待機するように設定することだけでした ;-)

    private const int MaxWaitTime = 5000;
    private SqlListener<RecordType> _recordListener;
    private RecordType _record;
    private readonly ManualResetEvent _recordWaiter = new ManualResetEvent(false);


    /// <summary>
    /// Request a record and wait until it is found.
    /// </summary>
    public RecordType GetRecordAwait(int requestedId)
    {
        // Initiate listening for record
        _recordListener = new SqlListener<RecordType>();
        _recordListener.SqlModified += SqlListener_SqlModified;
        _recordListener.StartListening(requestedId);

        // Wait synchronously until record is found
        _recordWaiter.WaitOne(MaxWaitTime);

        // Stop listening
        _recordListener.SqlModified -= SqlListener_SqlModified;
        _recordListener.Dispose();
        _recordListener = null;

        // Return record
        return _record;
    }

    private void SqlListener_SqlModified(object sender, SqlModifiedArgs args)
    {
        _record = (RecordType)args.Record;
        _recordWaiter.Set();
    }
于 2013-05-13T08:50:27.730 に答える