2013-05-07 56 views
1

我已经实现了一个使用SqlDependency等待SQL数据库中的更改的SqlListener类。在我的业务流程中,我需要等待数据库中出现一条记录。当找到请求的记录时,SqlListener触发一个事件。这工作正常。我可以通过输入一个While循环使其工作,并等待直到检测到返回的事件。但这不是理想的设计。这让处理器变得徒劳无功。等待来自SqlListener的事件

我想以更聪明的方式等待事件。我阅读了很多有关使用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; 
} 

回答

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

代替使用While,您可以使用Timer和事件。喜欢的东西:

public class ListenerWaiting 
{ 
    public ListenerWaiting(int waitingTimeSeconds) 
    { 
     _waitSeconds = waitingTimeSeconds; 
    } 

    private int _waitSeconds; 
    private System.Timers.Timer _timer; 
    private Listener _listener; 

    public event EventHandler<string> ListenerDone; 

    public void Listen(int listeningPeriodSeconds) 
    { 
     _listener = new Listener(listeningPeriodSeconds * 1000); 
     _listener.ListenerCompleted += ListenerListenerCompleted; 
     _timer = new System.Timers.Timer(_waitSeconds * 1000) {Enabled = true}; 
     _timer.Elapsed += TimerElapsed; 
    } 

    void ListenerListenerCompleted(object sender, string e) 
    { 
     StopTimer(); 
     StopListener(); 
     if (ListenerDone != null) 
      ListenerDone(this, "Waiting success! Message was: " + e); 
    } 

    void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     StopTimer(); 
     StopListener(); 
     if (ListenerDone != null) 
      ListenerDone(this, "Waited longer than set, aborted waiting..."); 
    } 

    private void StopTimer() 
    { 
     _timer.Stop(); 
     _timer.Elapsed -= TimerElapsed; 
     _timer = null; 
    } 

    private void StopListener() 
    { 
     _listener.ListenerCompleted -= ListenerListenerCompleted; 
     _listener = null; 
    } 
} 

public class Listener 
{ 
    private System.Timers.Timer _timer; 
    private string _listeningPeriodSeconds; 
    public event EventHandler<string> ListenerCompleted; 

    public Listener(int listeningPeriodSeconds) 
    { 
     _listeningPeriodSeconds = listeningPeriodSeconds.ToString(); 
     _timer = new System.Timers.Timer(listeningPeriodSeconds) { Enabled = true }; 
     _timer.Elapsed += TimerElapsed; 
    } 

    private void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     _timer.Elapsed -= TimerElapsed; 
     _timer = null; 
     if (ListenerCompleted != null) 
      ListenerCompleted(this, _listeningPeriodSeconds); 
    } 

} 

...,然后用使用它:

static void Main(string[] args) 
    { 
     var wait = new ListenerWaiting(5); 
     wait.ListenerDone += WaitListenerDone; 

     wait.Listen(3); 

     Console.ReadLine(); 
    } 

    static void WaitListenerDone(object sender, string e) 
    { 
     Console.WriteLine(e); 
    } 

我想我能找到更好的类的名字,但你会得到的想法;)

+0

谢谢你的关心,但是你的建议使我困惑。这真的是我的问题的解决方案吗?我的绊脚石是以“同步方式”等待事件。我知道我可以添加一个定时器来等待而不是while循环,但是定时器结果和事件结果仍然会在事件处理程序WaitListenerDone中出现。这将如何帮助我继续进行主要方法的连续工作流? – 2013-05-13 08:00:44