2016-06-19 5 views
1

は、私はあなたが一度だけ実行のために購読することができ、オブジェクトを処理するイベントを作成する興味や、アクションは自動的に解除C#ワンタイム(火一度)イベントの実装

ある.NETで同様のネイティブ機能はありますか? はここで今私のためにどのような作品である:ここではイベントが毎秒を実行するように設定されている

public class CustomTimer 
{ 
    private event Action OneSecond; 

    private readonly Timer timer; 

    // Registered actions that should be called only once 
    private readonly ICollection<Action> oneOffs; 

    public CustomTimer() 
    { 
     this.timer = new Timer { Interval = 1000 }; 
     this.timer.Elapsed += this.OnOneSecond; 
     this.oneOffs = new HashSet<Action>(); 
    } 

    public bool IsRunning => this.timer.Enabled; 

    public void Start() 
    { 
     this.timer.Start(); 
    } 

    public void Stop() 
    { 
     this.timer.Stop(); 
    } 

    public void Subscribe(Action callback) 
    { 
     this.OneSecond += callback; 
    } 

    public void SubscribeOnce(Action callback) 
    { 
     this.oneOffs.Add(callback); 
     this.Subscribe(callback); 
    } 

    public void Unsubscribe(Action callback) 
    { 
     this.OneSecond -= callback; 
     this.oneOffs.Remove(callback); 
    } 

    protected virtual void OnOneSecond(object sender, ElapsedEventArgs elapsedEventArgs) 
    { 
     this.OneSecond?.Invoke(); 
     this.UnsubscribeOneOffs(); 
    } 

    private void UnsubscribeOneOffs() 
    { 
     if (this.oneOffs.Count > 0) 
     { 
      foreach (var action in this.oneOffs) 
      { 
       this.OneSecond -= action; 
      } 

      this.oneOffs.Clear(); 
     } 
    } 
} 

にはどうすればUnsubscribeOneOffsは()メソッドの実行中に予期しない やイベントの実行を防止するためのイベントをトリガし、他のオブジェクトで同様の戦略を使用することができます。 何らかのロックを使用する必要がありますか?

答えて

1

OneSecondイベントハンドラとして1回のアクションを登録する必要はありません。別のリストに入れておくだけです。

public class CustomTimer 
{ 
    List<Action> _oneTimeActions = new List<Action>(); 

    public void SubscribeOnce(Action handler) 
    { 
     lock(_oneTimeActions) 
     { 
      _oneTimeActions.Add(handler); 
     } 
    } 


    protected virtual void OnOneSecond(object sender, ElapsedEventArgs elapsedEventArgs) 
    { 

      // get a local copy of scheduled one time items 
      // removing them from the list. 
      Action[] oneTimers; 

      lock(_oneTimeActions) 
      { 
       oneTimers = _oneTimeActions.ToArray(); 
       _oneTimeActions.Clear(); 
      }  

      // Execute periodic events first 
      this.OneSecond?.Invoke(); 

      // Now execute one time actions 
      foreach(var action in oneTimers) 
      { 
       action(); 
      } 
    } 
} 
関連する問題