2016-10-10 11 views
1

STOPPT, also habe ich ein System, in dem Sie einstellen können, um ein Taxi anzurufen (dies ist eine Spielanwendung), und dieses Taxi dauert 10 Sekunden, um zu kommen. Das Problem ist Ich habe auch eine Canceltaxi-Funktion und ich muss wissen, wie ich ein System.Threading.Timer stoppen kann, denn wenn sie ein Taxi bestellen, stornieren Sie es nach sagen wir 8 Sekunden dann direkt nachdem sie ein anderes Taxi, das Taxi bestellen dauert 2 Sekunden, um nicht 10 zu kommen, also benutzt es noch den alten Taxitimer, wie höre ich es auf?Wie man einen System.Threading.Timer

Ich habe diesen Code versucht, aber immer noch nicht aufhören .. Ich nenne diese Lücke, wenn ich es abbrechen möchte.

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

Voll Klasse:

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); 
     } 
    } 
} 

Auf 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

Try 'taxiTimerInstance.Change (Timeout.Infinite, Timeout.Infinite);' Sie werden dann zurückgesetzt, es auf 10 Sekunden auf die nächste Bestellung muss zurück. https://msdn.microsoft.com/en-us/library/yz1c7148(v=vs.110).aspx – TyCobb

Antwort

4

ich wissen muss, wie ich einen System.Threading.Timer stoppen können, weil, wenn sie ein Taxi zu bestellen, brechen sie nach sagen wir 8 Sekunden dann gerade, nachdem sie ein anderes Taxi zu bestellen, das Taxi dauert 2 Sekunden, um nicht 10 zu kommen, also benutzt es noch den alten Taxitimer, wie höre ich ihn auf?

Machen Sie einen Schritt zurück. Sie müssen sich keine Sorgen darüber machen, einen Timer zu löschen, wenn Sie nie einen machen.

Sie beschreiben einen asynchronen Workflow mit Abbruch. C# und das .NET-Framework verfügen bereits über diese Funktion. Verwenden Sie sie also, anstatt selbst zu rollen.

Machen Sie eine async Workflow-Methode, die await s eine Task.Delay Aufgabe, die eine CancellationToken dauert. Die Fortsetzung der Verspätung ist die Ankunft des Taxis; Die Annullierungsmethode bewirkt, dass die Aufgabe fehlschlägt, indem das Token storniert wird.

Es gibt viele Dokumentationen über diesen Mechanismus, also lesen Sie ihn. Ein guter Anfang ist hier:

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

1

Es scheint eine Menge cruft in Ihrem Code los zu sein. Es gibt ein paar Warnzeichen, die ich sehe.

Sie implementieren IDisposable nicht korrekt. Es sollte eher so sein:

Sie haben auch die Benennungskonvention für die Event-Raiting-Methode für den Event-Handler verwendet. Methoden zur Erhöhung der Ereignisse werden normalerweise On* genannt und die Methode zur Behandlung dieser Ereignisse ist *. In Ihrem Fall sollte es anstelle von public void OnTimerElapsed(object Obj) per Konvention public void TimerElapsed(object Obj) sein.

Außerdem fangen Sie eine Ausnahme mit catch (Exception ex). Das ist nur ein schlechtes Anti-Muster. Lesen Sie Eric Lippert's Vexing Exceptions.

Nun, schließlich würde ich vorschlagen, dass Sie diese Art von Klasse sowieso vermeiden. Verwenden Sie stattdessen Microsoft Reactive Framework (NuGet "System.Reactive").

Dann können Sie schreiben:

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); 
     }); 

Nun, wenn Sie für ein Taxi rufen Sie einfach requestTaxi.OnNext(roleplayInstance); schreiben. Wenn Sie dies ein zweites Mal anrufen, bevor das Taxi gerufen wird, startet das Event automatisch neu. Wenn Sie es mit requestTaxi.OnNext(null); aufrufen, bricht es jede aktuelle Anfrage ab, ist aber immer noch bereit, später mit einer neuen anzufangen.

Wenn Sie vollständig herunterfahren, rufen Sie subscription.Dispose();. Alles nur besser, denke ich.

0

Haben Sie die Tooltipps der Timer.Change-Methode gelesen? Versuchen Sie folgendes:

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