2016-10-10 20 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);