2012-08-13 36 views
9

Làm cách nào để dừng System.Threading.Timer trong phương thức gọi lại của nó. Tôi đã tham chiếu MSDN, nhưng không thể tìm thấy bất kỳ điều gì hữu ích. Hãy giúp tôi.Cách dừng System.Threading.Timer trong phương thức gọi lại

+0

Xem thêm http://stackoverflow.com/questions/6379541/reliably-stop-system-threading-timer –

+0

vâng tôi đã kiểm tra nó – Proceso

Trả lời

4
timer.Change(Timeout.Infinite, Timeout.Infinite); 
+0

Better vứt bỏ nó ngay sau đó. – usr

+1

nếu tôi muốn khởi động lại sau? – Volma

1

Bạn chỉ cần gọi myTimer.Change(Timeout.Infinite, Timeout.Infinite).

Về mặt kỹ thuật, chỉ cần tham số đầu tiên (dueTime) là Timeout.Infinite để hẹn giờ dừng.

Để biết thêm thông tin, hãy xem Timer.Change Method.

+0

Sẽ tốt hơn nếu vứt bỏ nó vì điều đó sẽ ghi lại ý nghĩa ngữ nghĩa tốt hơn. Nó cũng có thể nhanh hơn. – usr

+0

Tùy thuộc vào việc người dùng có dừng vĩnh viễn bộ hẹn giờ hay không hoặc họ có đang tạm dừng nó trong một thời gian hay không và có thể khởi động lại nó sau. Nếu bạn sử dụng '.Dispose()' để tạm dừng bộ đếm thời gian, bạn sẽ gặp phải vấn đề nếu bạn muốn khởi động lại hoặc chỉ cần thay đổi thời gian hoặc thời gian. Trong những trường hợp đó, nó an toàn hơn (và dễ dàng hơn) để chỉ sử dụng 'timer.Change()'. –

2

Hãy thử điều này:

Nếu bạn muốn, bạn có thể cho phép timer tiếp tục bắn phương pháp gọi lại và bao gồm mã dưới đây

private void CreatorLoop(object state) 
{ 
    if (Monitor.TryEnter(lockObject) 
    { 
    try 
    { 
     // Work here 
    } 
    finally 
    { 
     Monitor.Exit(lockObject); 
    } 
    } 
} 

kiểm tra liên kết này quá:

Stopping timer in its callback method

14

Đầu tiên, phương thức gọi lại phải có cá thể bộ đếm thời gian trong phạm vi.

Sau đó, câu thần chú đơn giản

timerInstance.Change(Timeout.Infinite , Timeout.Infinite) ; 

sẽ tắt bộ đếm thời gian. Có thể bộ hẹn giờ có thể gọi lại phương thức gọi lại một lần nữa sau khi thay đổi, tôi tin rằng, tùy thuộc vào trạng thái của nó.

+0

Tốt hơn là nên vứt bỏ nó vì điều đó sẽ ghi lại ý nghĩa ngữ nghĩa tốt hơn. Nó cũng có thể nhanh hơn. – usr

+3

Phụ thuộc vào việc bộ hẹn giờ có được khởi động lại sau đó hay bạn đã hoàn thành nó. OP quy định rằng cô ấy muốn "ngừng bộ hẹn giờ", chứ không phải "hủy bộ hẹn giờ". Ví dụ về thời gian và tuổi thọ của nó là trách nhiệm của người sáng tạo. –

+0

yap với giải pháp đó là vấn đề, luồng không dừng ngay lập tức. – Proceso

0

Tôi phát hiện ra một cách khó khăn mà Change (Timeout.Infinite, Timeout.Infinite) isn ' t khá đáng tin cậy, và chuyển sang System.Timers.Timer với AutoReset = false.

0

Sự cố với Bộ hẹn giờ là nó có thể được gọi sau khi xử lý lớp chủ sở hữu của nó. Việc thực hiện sau đây đã làm việc cho tôi bằng cách sử dụng đối tượng trạng thái của bộ khởi tạo Timer. Heap sẽ không loại bỏ đối tượng đó cho đến khi nó được tiêu thụ. Đây là cách duy nhất của tôi để dọn dẹp hẹn giờ một cách duyên dáng.

using System; 
using System.Threading; 

namespace TimerDispose 
{ 
    /// <summary> 
    /// A timer-containing class that can be disposed safely by allowing the timer 
    /// callback that it must exit/cancel its processes 
    /// </summary> 
    class TimerOwner : IDisposable 
    { 
     const int dueTime = 5 * 100;  //halve a second 
     const int timerPeriod = 1 * 1000; //Repeat timer every one second (make it Timeout.Inifinite if no repeating required) 

     private TimerCanceller timerCanceller = new TimerCanceller(); 

     private Timer timer; 

     public TimerOwner() 
     { 
      timerInit(dueTime); 
     } 

     byte[] dummy = new byte[100000]; 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="dueTime">Pass dueTime for the first time, then TimerPeriod will be passed automatically</param> 
     private void timerInit(int dueTime) 
     { 

      timer = new Timer(timerCallback, 
       timerCanceller,  //this is the trick, it will be kept in the heap until it is consumed by the callback 
       dueTime, 
       Timeout.Infinite 
      ); 

     } 

     private void timerCallback(object state) 
     { 
      try 
      { 
       //First exit if the timer was stoped before calling callback. This info is saved in state 
       var canceller = (TimerCanceller)state; 
       if (canceller.Cancelled) 
       { 
        return; // 
       } 

       //Your logic goes here. Please take care ! the callback might have already been called before stoping the timer 
       //and we might be already here after intending of stoping the timer. In most cases it is fine but try not to consume 
       //an object of this class because it might be already disposed. If you have to do that, hopefully it will be catched by 
       //the ObjectDisposedException below 




       dummy[1] = 50; //just messing up with the object after it might be disposed/nulled 

       //Yes, we need to check again. Read above note 
       if (canceller.Cancelled) 
       { 
        //Dispose any resource that might have been initialized above 
        return; // 
       } 

       if (timerPeriod != Timeout.Infinite) 
       { 
        timerInit(timerPeriod); 
       } 
      } 
      catch (ObjectDisposedException ex) 
      { 
       Console.WriteLine("A disposed object accessed"); 
      } 
      catch (NullReferenceException ex) 
      { 
       Console.WriteLine("A nulled object accessed"); 
      } 
      catch (Exception ex) 
      { 

      } 
     } 

     public void releaseTimer() 
     { 
      timerCanceller.Cancelled = true; 
      timer.Change(Timeout.Infinite, Timeout.Infinite); 
      timer.Dispose(); 
     } 

     public void Dispose() 
     { 
      releaseTimer(); 
      dummy = null; //for testing 
      GC.SuppressFinalize(this); 
     } 
    } 

    class TimerCanceller 
    { 
     public bool Cancelled = false; 
    } 


    /// <summary> 
    /// Testing the implementation 
    /// </summary> 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var list = new System.Collections.Generic.List<TimerOwner>(); 
      Console.WriteLine("Started initializing"); 
      for (int i = 0; i < 500000; i++) 
      { 
       list.Add(new TimerOwner()); 
      } 

      Console.WriteLine("Started releasing"); 
      foreach (var item in list) 
      { 
       item.Dispose(); 
      } 

      Console.WriteLine("Press any key to exit"); 
      Console.ReadKey(); 
     } 
    } 
} 
Các vấn đề liên quan