2016-11-10 4 views
2

일정 기간 동안 listBox1_SelectedValueChanged 이벤트를 등록 해제하는이 함수 세트가 있습니다.C# 일정 시간 동안 이벤트 사용 안 함

함수는 Pause()라고합니다.

일시 정지 (listBox1.SelectedValueChanged)

또는

일시 정지 (단추 1 :

같은 이벤트의 다양한 동일한 작업을 수행 할 수있는 기능으로, 일반적으로이 작업을 수행 할 수있는 방법이있다. 클릭)

등?

private System.Windows.Forms.Timer disableEvent = new System.Windows.Forms.Timer(); 
    private void Pause(int forTime = 200) 
    { 
     listBox1.SelectedValueChanged -= new EventHandler(listBox1_SelectedValueChanged); 

     disableEvent.Tick += new EventHandler(disableEvent_Tick); 
     disableEvent.Interval = (forTime); 
     disableEvent.Enabled = true; 
     disableEvent.Start(); 
    } 
    private void disableEvent_Tick(object sender, EventArgs e) 
    { 
     if (disableEvent.Enabled == true) 
     { 
      disableEvent.Tick -= new EventHandler(disableEvent_Tick);     
      disableEvent.Stop(); 
      disableEvent.Enabled = false; 

      listBox1.SelectedValueChanged += new EventHandler(listBox1_SelectedValueChanged); 
     } 
    } 
+0

모든 핸들러 지정된 이벤트를 일시 정지 할뿐만 아니라 하나 (귀하의 예제에서 listBox1_SelectedValueChanged)? – Evk

+0

모두는 아니지만 구체적입니다. 예를 들어 한 함수에서 listBox1_SelectedValueChanged를 일시 중지하고 싶습니다. 두 번째 함수에서 button1_Click 등을 일시 중지하고 싶습니다. –

+0

이 함수를 사용하여 '일반적인'메서드를 만들 수는 없지만 일부 이벤트는 param (구독 취소)으로 가져와야합니다. 당신은'event'는 객체가 될 수 없습니다. 'Button'에서 'stop'까지의 클릭 이벤트를 예로 들면 같은 유형의 다른 객체에 대해서만 이러한 함수를 수행 할 수 있습니다. 그냥 2 params, 개체 (버튼으로 예) 및 일부 위임 (un) 구독 방법을 보냅니다. – Shakra

답변

0

내가 (이 포럼에서 일부 코드를 사용)하는 방법을 발견했습니다, 그것은 작동하지만, 그건 작은 코드입니다 (좋아, 어쩌면 매우 복잡) 여기에 복잡 :

사용법 (몇 시간 동안 일시 정지) :

listBox1.Pause("listBox1_SelectedValueChanged", 3000); 
listBox1.Pause(3000); // to pause all events of listbox1 
button3.Pause("button3_Click", 10000); 

사용법 (재개까지 억제)

cEventSuppressor temp = listBox1.Suppress("listBox1_SelectedValueChanged"); 
cEventSuppressor temp = listBox1.Suppress(); //to suppress all 

사용량 (억제 후 - 재개)

,
temp.Resume("listBox1_SelectedValueChanged"); 
temp.Resume(); //To resume all 

나머지 :

#region Events 
public static class Events 
{   
    public static void Pause(this Control control, string eventName, int forTime) 
    { 
     EventTimers et = new EventTimers(); 
     et.PauseEvent(control, eventName, forTime); 
    } 

    public static void Pause(this Control control, int forTime) 
    { 
     EventTimers et1 = new EventTimers(); 
     et1.PauseEvent(control, forTime); 
    } 

    public static cEventSuppressor Suppress(this Control control, string eventName) 
    { 
     cEventSuppressor newControl = null; 
     newControl = new cEventSuppressor(control); 
     newControl.Suppress(eventName); 
     return newControl; 
    } 
    public static cEventSuppressor Suppress(this Control control) 
    { 
     cEventSuppressor newControl = null; 
     newControl = new cEventSuppressor(control); 
     newControl.Suppress(); 
     return newControl; 
    } 
} 

public class EventTimers 
{    
    private System.Windows.Forms.Timer disableEvent = new System.Windows.Forms.Timer(); 
    private cEventSuppressor suppressedControl { get; set; } 

    private static string eventName { get; set; } 

    //Pause specific Event 
    public void PauseEvent(Control control, string eventName, int forTime) 
    { 
     suppressedControl = new cEventSuppressor(control); 
     suppressedControl.Suppress(eventName);   

     disableEvent.Tick += new EventHandler(disableEvent_Tick); 
     disableEvent.Interval = (forTime); 
     disableEvent.Enabled = true; 
     disableEvent.Start(); 
    } 
    private void disableEvent_Tick(object sender, EventArgs e) 
    { 
     if (disableEvent.Enabled == true) 
     { 
      disableEvent.Tick -= new EventHandler(disableEvent_Tick); 
      disableEvent.Stop(); 
      disableEvent.Enabled = false; 

      suppressedControl.Resume(eventName); 
     } 
    } 

    //Pause All Events 
    public void PauseEvent(Control control, int forTime) 
    { 
     suppressedControl = new cEventSuppressor(control); 
     suppressedControl.Suppress(); 

     disableEvent.Tick += new EventHandler(disableEvent_Tick2); 
     disableEvent.Interval = (forTime); 
     disableEvent.Enabled = true; 
     disableEvent.Start(); 
    } 
    private void disableEvent_Tick2(object sender, EventArgs e) 
    { 
     if (disableEvent.Enabled == true) 
     { 
      disableEvent.Tick -= new EventHandler(disableEvent_Tick2); 
      disableEvent.Stop(); 
      disableEvent.Enabled = false; 

      suppressedControl.Resume(); 
     } 
    } 

}  
public class cEventSuppressor 
{ 
    Control _source; 
    EventHandlerList _sourceEventHandlerList; 
    FieldInfo _headFI; 
    Dictionary<object, Delegate[]> suppressedHandlers = new Dictionary<object, Delegate[]>(); 
    PropertyInfo _sourceEventsInfo; 
    Type _eventHandlerListType; 
    Type _sourceType; 

    public cEventSuppressor(Control control) 
    { 
     if (control == null) 
      throw new ArgumentNullException("control", "An instance of a control must be provided."); 

     _source = control; 
     _sourceType = _source.GetType(); 
     _sourceEventsInfo = _sourceType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); 
     _sourceEventHandlerList = (EventHandlerList)_sourceEventsInfo.GetValue(_source, null); 
     _eventHandlerListType = _sourceEventHandlerList.GetType(); 
     _headFI = _eventHandlerListType.GetField("head", BindingFlags.Instance | BindingFlags.NonPublic); 
    } 
    private Dictionary<object, Delegate[]> BuildList() 
    { 
     Dictionary<object, Delegate[]> retval = new Dictionary<object, Delegate[]>(); 
     object head = _headFI.GetValue(_sourceEventHandlerList); 
     if (head != null) 
     { 
      Type listEntryType = head.GetType(); 
      FieldInfo delegateFI = listEntryType.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic); 
      FieldInfo keyFI = listEntryType.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); 
      FieldInfo nextFI = listEntryType.GetField("next", BindingFlags.Instance | BindingFlags.NonPublic); 
      retval = BuildListWalk(retval, head, delegateFI, keyFI, nextFI); 
     } 
     return retval; 
    } 

    private Dictionary<object, Delegate[]> BuildListWalk(Dictionary<object, Delegate[]> dict, 
           object entry, FieldInfo delegateFI, FieldInfo keyFI, FieldInfo nextFI) 
    { 
     if (entry != null) 
     { 
      Delegate dele = (Delegate)delegateFI.GetValue(entry); 
      object key = keyFI.GetValue(entry); 
      object next = nextFI.GetValue(entry); 

      if (dele != null) 
      { 
       Delegate[] listeners = dele.GetInvocationList(); 
       if (listeners != null && listeners.Length > 0) 
       { 
        dict.Add(key, listeners); 
       } 
      } 
      if (next != null) 
      { 
       dict = BuildListWalk(dict, next, delegateFI, keyFI, nextFI); 
      } 
     } 
     return dict; 
    } 
    public void Resume() 
    { 
     Resume(null); 
    } 
    public void Resume(string pMethodName) 
    { 
     //if (_handlers == null) 
     // throw new ApplicationException("Events have not been suppressed."); 
     Dictionary<object, Delegate[]> toRemove = new Dictionary<object, Delegate[]>(); 

     // goes through all handlers which have been suppressed. If we are resuming, 
     // all handlers, or if we find the matching handler, add it back to the 
     // control's event handlers 
     foreach (KeyValuePair<object, Delegate[]> pair in suppressedHandlers) 
     { 

      for (int x = 0; x < pair.Value.Length; x++) 
      { 

       string methodName = pair.Value[x].Method.Name; 
       if (pMethodName == null || methodName.Equals(pMethodName)) 
       { 
        _sourceEventHandlerList.AddHandler(pair.Key, pair.Value[x]); 
        toRemove.Add(pair.Key, pair.Value); 
       } 
      } 
     } 
     // remove all un-suppressed handlers from the list of suppressed handlers 
     foreach (KeyValuePair<object, Delegate[]> pair in toRemove) 
     { 
      for (int x = 0; x < pair.Value.Length; x++) 
      { 
       suppressedHandlers.Remove(pair.Key); 
      } 
     } 
     //_handlers = null; 
    } 
    public void Suppress() 
    { 
     Suppress(null); 
    } 
    public void Suppress(string pMethodName) 
    { 
     //if (_handlers != null) 
     // throw new ApplicationException("Events are already being suppressed."); 

     Dictionary<object, Delegate[]> dict = BuildList(); 

     foreach (KeyValuePair<object, Delegate[]> pair in dict) 
     { 
      for (int x = pair.Value.Length - 1; x >= 0; x--) 
      { 
       //MethodInfo mi = pair.Value[x].Method; 
       //string s1 = mi.Name; // name of the method 
       //object o = pair.Value[x].Target; 
       // can use this to invoke method pair.Value[x].DynamicInvoke 
       string methodName = pair.Value[x].Method.Name; 

       if (pMethodName == null || methodName.Equals(pMethodName)) 
       { 
        _sourceEventHandlerList.RemoveHandler(pair.Key, pair.Value[x]); 
        suppressedHandlers.Add(pair.Key, pair.Value); 
       } 
      } 
     } 
    } 
} 
#endregion 
1

필드에 대해 DateTime 필드를 사용합니다. 실행이 허용되면 SelectedValuedChanged() 이벤트를 체크합니다. (의사) 그것은 어떤 당신에게 타이머 및 복잡성을 절약 할 수

public class Class1 
{ 
    private DateTime _isEnabledAfter = DateTime.MinValue; 

    public Class() 
    { 
     listBox1.SelectedValueChanged += new EventHandler(listBox1_SelectedValueChanged); 
    } 

    public void Pause(int timeMS) 
    { 
     // set the _isEnabledAfter in the future. 
     _isEnabledAfter = DateTime.Now.AddMilliseconds(timeMS); 
    } 


    public void listBox1_SelectedValueChanged(object sender, EventArgs e) 
    { 
     // is it after _isEnabledAfter? 
     if(DateTime.Now < _isEnabledAfter) 
      // nope... do nothing. 
      return; 

     // do your thing. 
    } 

} 

: 는 예를 들어

(이벤트를 unreguster하지 않음).

public class Class1 
{ 
    private TimeEnabledEvent _selectedValueChanged = new TimeEnabledEvent(); 

    public Class1() 
    { 
     listBox1.SelectedValueChanged += (s, e) => 
     { 
      if (_selectedValueChanged.IsEnabled) 
       listBox1_SelectedValueChanged(s, e); 
     }; 


     _selectedValueChanged.Pause(200); 
    } 


    public void listBox1_SelectedValueChanged(object sender, EventArgs e) 
    { 
     // do your thing. 
    } 

} 

public class TimeEnabledEvent 
{ 
    private DateTime _isEnabledAfter = DateTime.MinValue; 

    public void Pause(int timeMS) 
    { 
     // set the _isEnabledAfter in the future. 
     _isEnabledAfter = DateTime.Now.AddMilliseconds(timeMS); 
    } 

    public bool IsEnabled 
    { 
     get { return (DateTime.Now >= _isEnabledAfter); } 
    } 
} 

업데이트 2 :

public partial class Form1 : Form 
{ 
    private TimeEnabledEvent _event = new TimeEnabledEvent(); 

    public Form1() 
    { 
     InitializeComponent(); 
     listBox1.SelectedValueChanged += _event.Check(ListBox1_SelectedValueChanged); 
     _event.Pause(1000); 
    } 

    private void ListBox1_SelectedValueChanged(object sender, EventArgs e) 
    { 
     // do your thing 
    } 
} 

01,235


은 다음과 같이 될 수 있을까 NuGet "System.Reactive"- - 16,

internal class TimeEnabledEvent 
{ 
    internal EventHandler Check(EventHandler listBox1_SelectedValueChanged) 
    { 
     return new EventHandler((ss, ee) => 
     { 
      if (DateTime.Now >= _isEnabledAfter) 
       listBox1_SelectedValueChanged(ss, ee); 
     }); 
    } 

    private DateTime _isEnabledAfter = DateTime.MinValue; 

    public void Pause(int timeMS) 
    { 
     // set the _isEnabledAfter in the future. 
     _isEnabledAfter = DateTime.Now.AddMilliseconds(timeMS); 
    } 

} 
+0

글쎄, 내 솔루션 이상에서 멀리있을 수도 있지만 작동합니다. 문제는 listBox1.SelectedValueChanged뿐만 아니라 모든 이벤트에 대해 보편적으로 수행하는 것입니다. –

+0

그런 다음 이벤트가있는 프록시 개체를 만듭니다. –

+0

제발 그걸 어떻게 보여 주실 수 없습니까? –

0

나는 마이크로 소프트의 반응성 프레임 워크를 사용합니다 다음이 작업을 수행 할 수 있습니다

bool pause = false; 

IObservable<EventPattern<EventArgs>> observable = 
    Observable 
     .FromEventPattern<EventHandler, EventArgs>(
      h => listBox1.SelectedIndexChanged += h, 
      h => listBox1.SelectedIndexChanged -= h) 
     .Where(ep => pause != true); 

IDisposable subscription = 
    observable 
     .Subscribe(ep => listBox1_SelectedValueChanged(ep.Sender, ep.EventArgs)); 

지금 바로 이벤트 처리를 일시 중지됩니다 truefalse에서 pause의 값을 변경.

핸들러를 분리하려면 subscription.Dispose()을 호출하면됩니다.

0

ManualResetEvent과 같이 WaitHandle을 사용하고 싶습니다. 여러 이벤트를 독립적으로 일시 중단하려면 다른 ManualResetEvent을 사용하십시오.

내가 이런 식으로 구현 것 :

private ManualResetEvent pauseListBox1; 
private ManualResetEvent pauseButton1; 

가 일시 정지를 시작하려면, 내가 사용하는 것 :

pauseListBox1.Set(); 

을 일시 중지를 종료하려면, 내가 사용하십시오 :

pauseListBox1.Reset(); 

이벤트 처리기에서이 값을 사용합니다.

// Return from the event handler of the even is set 
if (WaitHandle.WaitOne(1)) 
    return; 
0

일반적인 방법으로 어떻게 할 수 있는지 구체적으로 답변 해 드리겠습니다. 일시 중지 절차 자체를 개선하는 방법은 이미 답변되었습니다.

이벤트 참조를 다른 메서드로 전달할 수는 없지만 약간의 리플렉션으로 이벤트 참조를 전달할 수는 있습니다. 예를 들어

private static void Pause<TSource, TEvent>(TSource source, Expression<Func<TSource, TEvent>> eventRef, TEvent handler, int forTime = 200) { 
    var ev = source.GetType().GetEvent(((MemberExpression)eventRef.Body).Member.Name); 
    // source.eventRef -= handler; 
    ev.RemoveMethod.Invoke(source, new object[] { handler }); 
    // do some stuff 
    // source.eventRef += handler; 
    ev.AddMethod.Invoke(source, new object[] { handler }); 
} 

사용 이벤트는 다음과 같이 구현되는 경우에만 작동이 불행하게도

Pause(listBox1, c => c.SelectedValueChanged, listBox1_SelectedValueChanged); 

입니다 :

public event SomeDelegate MyEvent; 

그것은 다음과 같이 구현된다 (모두의 WinForm 컨트롤 이벤트를 구현하는 경우 이런)

public event SomeDelegate MyEvent { 
    add { 
     // do something 
    } 
    remove { 
     // do something 
    } 
} 

표현식을 통해 이러한 이벤트 참조를 전달할 수 없기 때문에 더 이상 작동하지 않습니다. 그러나 표현식은 이벤트 이름을 얻기 위해 편의상 사용됩니다. 그래서 당신은 명시 적으로 이벤트 이름을 전달할 수 있습니다

private static void Pause<TSource, TEvent>(TSource source, string eventName, TEvent handler, int forTime = 200) { 
    var ev = source.GetType().GetEvent(eventName); 
    // source.eventRef -= handler; 
    ev.RemoveMethod.Invoke(source, new object[] { handler }); 
    // do some stuff 
    // source.eventRef += handler; 
    ev.AddMethod.Invoke(source, new object[] { handler }); 
} 

사용은

Pause<ListBox, EventHandler>(listBox1, nameof(listBox1.SelectedValueChanged), listBox1_SelectedValueChanged); 

적은 꽤된다하지만 여전히 작동합니다.

+0

정확히 원하는대로 잘 보이지만이 오류를 내게줍니다 : http://imgur.com/a/m9V3O –

+0

설명한대로 Pause가 정확히 구현 되었습니까? 나는 그것을 테스트하고 확실히 작동하는지 확신합니다. – Evk

+0

나는 이걸 좀 보라 : http://imgur.com/a/LkXJH –