2009-03-15 19 views
13

Tôi cần có thể trì hoãn trình xử lý sự kiện cho một số điều khiển (như nút) được kích hoạt chẳng hạn sau 1 giây sự kiện (sự kiện bấm ví dụ) .. là điều này có thể bởi khung .net?Có cách nào để trì hoãn trình xử lý sự kiện (nói 1 giây) trong Windows Forms

Tôi sử dụng bộ hẹn giờ và gọi mã của tôi từ sự kiện đánh dấu của bộ hẹn giờ như dưới đây nhưng tôi không chắc đây có phải là cách tiếp cận tốt nhất hay không!

void onButtonClick(..) 
{ 
    timer1.Enabled = true; 
} 

void onTimerTick(..) 
{ 
    timer.Enabled = false; 

    CallMyCodeNow(); 
} 
+2

Đây có thể là cách phù hợp để thực hiện. – configurator

Trả lời

5

Trước khi đến câu hỏi của bạn, chỉ cần sau khi đọc các bit tóm tắt từ trang câu hỏi chính, một bộ đếm thời gian chính xác là những gì tôi đã đi để đề nghị.

Điều này có vẻ khá sạch sẽ đối với tôi. Nó có nghĩa là bạn có thể dễ dàng "hủy bỏ" sự kiện bị trì hoãn nếu bạn cần, bằng cách vô hiệu hóa bộ đếm thời gian một lần nữa, ví dụ. Nó cũng làm tất cả mọi thứ trong thread UI (nhưng không có reentrancy), làm cho cuộc sống đơn giản hơn một chút so với các lựa chọn thay thế khác.

-3

Bạn có thể sử dụng:

Thread.Sleep(1000); 

Điều đó sẽ tạm dừng Chủ đề hiện tại trong một giây. Vì vậy, tôi sẽ làm điều đó ...

Trân trọng!

+1

Điều đó sẽ khiến cho chuỗi giao diện người dùng bị treo, điều này không bao giờ là điều tốt. Sử dụng Bộ hẹn giờ sẽ cho phép máy bơm thông báo xử lý. –

15

Có lẽ bạn có thể tạo phương pháp tạo hẹn giờ?

void onButtonClick(object sender, EventArgs e) 
{ 
    Delay(1000, (o,a) => MessageBox.Show("Test")); 
} 

static void Delay(int ms, EventHandler action) 
{ 
    var tmp = new Timer {Interval = ms}; 
    tmp.Tick += new EventHandler((o, e) => tmp.Enabled = false); 
    tmp.Tick += action; 
    tmp.Enabled = true; 
} 
+0

Đã khắc phục lỗi chính tả có thể xảy ra. Lời cầu xin quay trở lại nếu tôi phạm sai lầm. – strager

+0

Được cuộn lại, bạn không thể sử dụng cùng tên cho thông số lambda. – Bengt

+0

Ah, phải. Lấy làm tiếc. xD – strager

5

Nếu bạn chỉ thực hiện việc này cho một điều khiển, phương pháp hẹn giờ sẽ hoạt động tốt. Một cách tiếp cận mạnh mẽ hơn hỗ trợ nhiều kiểm soát và loại sự kiện trông giống như sau:

class Event 
{ 
    public DateTime StartTime { get; set; } 
    public Action Method { get; set; } 

    public Event(Action method) 
    { 
     Method = method; 
     StartTime = DateTime.Now + TimeSpan.FromSeconds(1); 
    } 
} 

Duy trì một Queue<Event> trong biểu mẫu và có giao diện người dùng sự kiện mà cần phải được trì hoãn thêm chúng vào hàng đợi, ví dụ:

void onButtonClick(..) 
{ 
    EventQueue.Enqueue(new Event(MethodToCall)); 
} 

Hãy hẹn giờ đánh dấu của bạn 10 lần một giây hoặc lâu hơn, và có xử lý sự kiện Tick của nó trông như thế này:

void onTimerTick() 
{ 
    if (EventQueue.Any() && EventQueue.First().StartTime >= DateTime.Now) 
    { 
     Event e = EventQueue.Dequeue(); 
     e.Method; 
    } 
} 
+0

Tôi nghĩ rằng việc sử dụng 'MinHeap' hoặc' SortedList' sẽ tốt hơn sử dụng Hàng đợi vì thời gian trễ sự kiện có thể không nhất thiết phải giống nhau. Nếu không, sử dụng 'Danh sách' thông thường và lặp lại tất cả các sự kiện trong đó sẽ là tùy chọn tiếp theo. –

0

Nếu bạn đang tìm kiếm một ưa thích hơn giải pháp, bạn có thể muốn xem xét Phản ứng của tôi LINQ project. Liên kết không hiển thị cách giải quyết vấn đề cụ thể mà bạn đang gặp phải, nhưng có thể giải quyết theo kiểu khá thanh lịch bằng cách sử dụng kỹ thuật được mô tả ở đó (trong toàn bộ chuỗi 4 bài).

4

giải pháp của tôi sử dụng System.Threading.Timer:

public static class ExecuteWithDelay 
{ 
    class TimerState 
    { 
     public Timer Timer; 
    } 

    public static Timer Do(Action action, int dueTime) 
    { 
     var state = new TimerState(); 
     state.Timer = new Timer(o => 
     { 
      action(); 
      lock (o) // The locking should prevent the timer callback from trying to free the timer prior to the Timer field having been set. 
      { 
       ((TimerState)o).Timer.Dispose(); 
      } 
     }, state, dueTime, -1); 
     return state.Timer; 
    } 
} 
2

Đối với những giới hạn trong .NET 2.0, đây là một gánh vác giải pháp hữu ích Bengt của:

/// <summary> 
/// Executes the specified method in a delayed context by utilizing 
/// a temporary timer. 
/// </summary> 
/// <param name="millisecondsToDelay">The milliseconds to delay.</param> 
/// <param name="methodToExecute">The method to execute.</param> 
public static void DelayedExecute(int millisecondsToDelay, MethodInvoker methodToExecute) 
{ 
    Timer timer = new Timer(); 
    timer.Interval = millisecondsToDelay; 
    timer.Tick += delegate 
         { 
          // This will be executed on a single (UI) thread, so lock is not necessary 
          // but multiple ticks may have been queued, so check for enabled. 
          if (timer.Enabled) 
          { 
           timer.Stop(); 

           methodToExecute.Invoke(); 

           timer.Dispose(); 
          } 
         }; 

    timer.Start(); 
} 
1

Sử dụng Extensions phản hồi:

Trước tiên, hãy cài đặt gói nuget

PM> Install-Package Rx-Main 

Mã số:

private void CallMyCodeNow() 
    { 
     label1.Text = "reactivated!"; 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     var o = Observable.FromEventPattern<EventHandler, EventArgs>(
      handler => button1.Click += handler 
      , handler => button1.Click -= handler 
      ) 
      .Delay(TimeSpan.FromSeconds(5)) 
      .ObserveOn(SynchronizationContext.Current) // ensure event fires on UI thread 
      .Subscribe(
       ev => CallMyCodeNow() 
       , ex => MessageBox.Show(ex.Message) 
      ); 
    } 
Các vấn đề liên quan