2016-10-10 48 views
1

所以我有一個系統,您可以設置打電話給出租車(這是一個遊戲應用程序),而這輛出租車需要10秒鐘才能到達。問題是 我也有一個canceltaxi函數,我需要知道如何停止System.Threading.Timer,因爲當他們點了一輛出租車後,取消它後 可以說8秒,然後他們點了另一輛出租車後,那輛出租車需要2秒鐘來不到10所以它仍然使用舊的計時器, 我該如何阻止它?如何停止System.Threading.Timer

我已經試過這段代碼,但它仍然沒有停止..當我想取消它時,我稱之爲無效。

public void StopTaxiTimer() 
     { 
      taxiTimerInstance.Dispose(); 
      taxiTimerInstance = null; 
      this.Dispose(); 
     } 

滿級:

using log4net; 
using Plus.Communication.Packets.Outgoing.Rooms.Chat; 
using Plus.HabboHotel.GameClients; 
using Plus.HabboHotel.Roleplay.Instance; 
using Plus.HabboHotel.Rooms; 
using System; 
using System.Threading; 

namespace Plus.HabboHotel.Roleplay.Timers 
{ 
    public sealed class TaxiTimer : IDisposable 
    { 
     private static readonly ILog myLogger = LogManager.GetLogger("Plus.HabboHotel.Roleplay.Timers.DeathTimer"); 

     private Timer taxiTimerInstance; 
     private uint timerTimeSeconds; 
     private RoleplayInstance roleplayInstance; 

     public TaxiTimer(RoleplayInstance roleplayInstance) 
     { 
      Console.WriteLine("Setup TaxiTimer for " + roleplayInstance.GetSession().GetHabbo().Username + " (" + roleplayInstance.TaxiWaitTimeSeconds + " seconds)"); 
      this.timerTimeSeconds = roleplayInstance.TaxiWaitTimeSeconds; 
      this.roleplayInstance = roleplayInstance; 
      this.taxiTimerInstance = new Timer(new TimerCallback(this.OnTimerElapsed), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); 
     } 

     public void OnTimerElapsed(object Obj) 
     { 
      try 
      { 
       if (taxiTimerInstance == null) 
        return; 

       if (roleplayInstance == null || !roleplayInstance.CalledTaxi || roleplayInstance.GetSession() == null || roleplayInstance.GetSession().GetHabbo() == null) 
        return; 

       GameClient gameSession = roleplayInstance.GetSession(); 

       if (roleplayInstance.TaxiWaitTimeSeconds < 1) 
       { 
        Room currentRoom = gameSession.GetHabbo().CurrentRoom; 
        if (currentRoom == null) 
         return; 

        RoomUser roomUser = currentRoom.GetRoomUserManager().GetRoomUserByHabbo(gameSession.GetHabbo().Id); 
        if (roomUser == null) 
         return; 

        roleplayInstance.CalledTaxi = false; 
        currentRoom.SendMessage(new ShoutComposer(roomUser.VirtualId, "*Gets transported to my destination*", 0, roomUser.LastBubble)); 
        gameSession.GetHabbo().PrepareRoom(roleplayInstance.TaxiRoomId, string.Empty); 
       } 
       else 
       { 
        roleplayInstance.TaxiWaitTimeSeconds--; 
       } 
      } 
      catch (Exception ex) 
      { 
       myLogger.Error(ex.Message); 
       myLogger.Error(ex.StackTrace); 
      } 
     } 

     public void StopTaxiTimer() 
     { 
      taxiTimerInstance.Dispose(); 
      taxiTimerInstance = null; 
      this.Dispose(); 
     } 

     public void Dispose() 
     { 
      GC.SuppressFinalize(this); 
     } 
    } 
} 

在CallTaxi:

roleplayInstance.TaxiWaitTimeSeconds = Convert.ToUInt32(PlusEnvironment.GetRPManager().GetSettings().GetSettingValueByKey("roleplay_taxi_wait_seconds")); 
        roleplayInstance.TaxiRoomId = goingTo.RoomId; 
        roleplayInstance.TaxiTimer = new HabboHotel.Roleplay.Timers.TaxiTimer(roleplayInstance); 
+0

嘗試'taxiTimerInstance.Change(Timeout.Infinite,Timeout.Infinite);'然後,您將不得不重新回至10秒的下一個數量級上。 https://msdn.microsoft.com/en-us/library/yz1c7148(v=vs.110).aspx – TyCobb

回答

4

我需要知道我怎麼能停止System.Threading.Timer因爲當他們訂購了一輛出租車,將其取消後可以比如說8秒鐘,然​​後伸直後他們爲了另一部的士,的士需要2秒鐘不到10秒,所以它仍然使用舊的計時器,我該如何阻止它?

退一步。如果您從未製作過定時器,則不必擔心取消定時器。

您正在描述一個取消的異步工作流程。 C#和.NET框架已經有了這個功能,所以使用它而不是試圖推出自己的。

製作async工作流方法await s Task.Delay任務需要CancellationToken。延誤的延續是出租車的到來;取消方法通過取消令牌導致任務失敗。

這個機制有很多文檔,所以開始閱讀它。一個良好的開始是在這裏:

https://msdn.microsoft.com/en-us/library/dd997364

1

好像有很多冗餘代碼的代碼中的事。我看到一些警告標誌。

您沒有正確實施IDisposable。它應該更像這樣:

public class ExampleDisposable : IDisposable 
{ 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      // free managed resources 
     } 
     // free native resources if there are any. 
    } 
} 

您還使用事件處理程序的事件引發方法命名約定。提高事件的方法通常稱爲On*,處理這些事件的方法是*。所以,在你的情況下,而不是public void OnTimerElapsed(object Obj)按慣例應該是public void TimerElapsed(object Obj)

此外,您正在接受catch (Exception ex)的例外。這只是一個糟糕的反模式。閱讀Eric Lippert's Vexing Exceptions

現在,最後,我建議你避免這種類。改用微軟的Reactive框架(NuGet「System.Reactive」)。當你想叫你只是寫requestTaxi.OnNext(roleplayInstance);出租車

Subject<RoleplayInstance> requestTaxi = new Subject<RoleplayInstance>(); 

IDisposable subscription = 
    requestTaxi 
     .Select(ri => 
      ri == null 
      ? Observable.Never<RoleplayInstance>() 
      : Observable 
       .Timer(TimeSpan.FromSeconds((double)ri.TaxiWaitTimeSeconds)) 
       .Select(n => ri)) 
     .Switch() 
     .Subscribe(ri => 
     { 
      GameClient gameSession = ri.GetSession(); 
      Room currentRoom = gameSession.GetHabbo().CurrentRoom; 
      RoomUser roomUser = currentRoom.GetRoomUserManager().GetRoomUserByHabbo(gameSession.GetHabbo().Id); 
      currentRoom.SendMessage(new ShoutComposer(roomUser.VirtualId, "*Gets transported to my destination*", 0, roomUser.LastBubble)); 
      gameSession.GetHabbo().PrepareRoom(roleplayInstance.TaxiRoomId, string.Empty); 
     }); 

現在:

然後,你可以這樣寫。如果您在打車之前再次打電話,該事件會自動重新啓動。如果使用requestTaxi.OnNext(null);調用它,則會取消當前的任何請求,但仍可以稍後處理新請求。

如果您完全關閉,請致電subscription.Dispose();。我想所有的人都很整潔。

0

您是否閱讀過Timer.Change方法上的工具提示?試試這個:

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