2016-05-23 7 views
2

JSクライアントにサーバー送信イベントを使用してメッセージを送信しようとしています。クライアントは、6回目または7回目のイベントごとに取得します。私は間違って何をしていますか?IServerEvents.NotifyChannelを使用しているイベントがありません

行動は、単純なスタンドアロンのサンプル使用して再現することができます。

using System; 
using System.Threading; 

using Funq; 
using ServiceStack; 

namespace ServerSentEvents 
{ 
    public class AppHost : AppSelfHostBase 
    { 
     /// <summary> 
     /// Default constructor. 
     /// Base constructor requires a name and assembly to locate web service classes. 
     /// </summary> 
     public AppHost() 
      : base("ServerSentEvents", typeof(AppHost).Assembly) 
     { 

     } 

     /// <summary> 
     /// Application specific configuration 
     /// This method should initialize any IoC resources utilized by your web service classes. 
     /// </summary> 
     /// <param name="container"></param> 
     public override void Configure(Container container) 
     { 
      SetConfig(new HostConfig 
      { 
#if DEBUG 
       DebugMode = true, 
       WebHostPhysicalPath = "~/../..".MapServerPath(), 
#endif 
      }); 

      container.Register<IServerEvents>(c => new MemoryServerEvents()); 
      Plugins.Add(new ServerEventsFeature 
      { 
       OnPublish = (res, msg) => 
       { 
        // Throws an exception 
        //res.Write("\n\n\n\n\n\n\n\n\n\n"); // Force flush: http://stackoverflow.com/questions/25960723/servicestack-sever-sent-events/25983774#25983774 
        //res.Flush(); 
       } 
      }); 

      container.Register(new FrontendMessages(container.Resolve<IServerEvents>())); 
     } 
    } 

    public class FrontendMessage 
    { 
     public string Level { get; set; } 
     public string Message { get; set; } 
    } 

    public class FrontendMessages 
    { 
     private readonly IServerEvents _serverEvents; 
     private Timer _timer; 

     public FrontendMessages(IServerEvents serverEvents) 
     { 
      if (serverEvents == null) throw new ArgumentNullException(nameof(serverEvents)); 
      _serverEvents = serverEvents; 

      var ticks = 0; 
      _timer = new Timer(_ => Info($"Tick {ticks++}"), null, 500, 500); 
     } 

     public void Info(string message, params object[] parameters) 
     { 
      var frontendMessage = new FrontendMessage 
      { 
       Level = "success", 
       Message = message 
      }; 

      Console.WriteLine("Sending message: " + frontendMessage.Message); 
      _serverEvents.NotifyChannel("messages", frontendMessage); 
     } 
    } 
} 

とクライアント:問題はあなたです

Message from server Object {Level: "success", Message: "Tick 28"} 
Message from server Object {Level: "success", Message: "Tick 35"} 
Message from server Object {Level: "success", Message: "Tick 42"} 
Message from server Object {Level: "success", Message: "Tick 49"} 
+1

[この質問](http:// stackoverflo w.com/questions/25960723/servicestack-sever-sent-events?lq=1)?それは似ています –

+0

はい、サンプルでわかるように、私は示唆されたOnPublishコードを含みました。私はこのケースでは例外をスローするので、コメントアウトしました。それは私の現実世界のコード思考を投げているわけではありません。しかし、それはどちらもうまくいかない。 –

答えて

2

:よう

<!DOCTYPE html> 

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <meta charset="utf-8" /> 
    <title></title> 
    <script src="js/jquery-1.11.1.min.js"></script> 
    <script src="js/ss-utils.js"></script> 
</head> 
<body> 
<script> 
    // Handle messages 
    var msgSource = new EventSource('event-stream?channel=messages&t=' + new Date().getTime()); 
    $(msgSource).handleServerEvents({ 
     handlers: { 
      FrontendMessage: function (msg) { 
       console.log('Message from server', msg); 
      } 
     } 
    }); 
</script> 
</body> 
</html> 

コンソールログが見えますの前にIServerEventsにメッセージを送信しようとしていますが初期化された後ではなく、すぐにAppHost.Configure()で開始するので、は登録されています。問題の実際の原因は、タイマーの起動時にIdleTimeoutが適切に初期化されていないため、各サーバーイベント接続の有効期間が00:00:00になり、自動的に破棄されて自動再接続されるメッセージよりもメッセージを受け取ることになります再び - 全体のプロセスには約6-7を取る彼らは追加しているとき

ServiceStack Pluginsが登録されていない:)ダニ、彼らは他のプラグインを前に、他のプラグインを追加/削除/検査する機会を与えるAppHost.Configure()後に一緒に登録します彼らは登録されています。 MemoryServerEventsはデフォルトであるため、登録する必要はありません。recommended way to initialize a timer with an intervalは、タイマーコールバックでtimer.Change()を使用します。唯一すなわち、Start()が明示的に呼び出されたときに起動

public class AppHost : AppSelfHostBase 
{ 
    public AppHost() 
     : base("ServerSentEvents", typeof(AppHost).Assembly) { } 

    public override void Configure(Container container) 
    { 
     SetConfig(new HostConfig { 
#if DEBUG 
      DebugMode = true, 
      WebHostPhysicalPath = "~/../..".MapServerPath(), 
#endif 
     }); 

     Plugins.Add(new ServerEventsFeature()); 
     container.Register(c => new FrontendMessages(c.Resolve<IServerEvents>())); 
    } 
} 

そして、あなたのFrontendMessagesを持っている:APPHOSTがされた後

public class FrontendMessage 
{ 
    public string Level { get; set; } 
    public string Message { get; set; } 
} 

public class FrontendMessages 
{ 
    private readonly IServerEvents _serverEvents; 
    private Timer _timer; 

    public FrontendMessages(IServerEvents serverEvents) 
    { 
     if (serverEvents == null) throw new ArgumentNullException(nameof(serverEvents)); 
     _serverEvents = serverEvents; 
    } 

    public void Start() 
    { 
     var ticks = 0; 
     _timer = new Timer(_ => { 
      Info($"Tick {ticks++}"); 
      _timer.Change(500, Timeout.Infinite); 
     }, null, 500, Timeout.Infinite); 
    } 

    public void Info(string message, params object[] parameters) 
    { 
     var frontendMessage = new FrontendMessage { 
      Level = "success", 
      Message = message 
     }; 

     Console.WriteLine("Sending message: " + frontendMessage.Message); 
     _serverEvents.NotifyChannel("messages", frontendMessage); 
    } 
} 

そして、それだけを開始し、私のようにあなたのAPPHOSTを書き換えるだろうこれを考えると

すなわち:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var appHost = new AppHost() 
      .Init() 
      .Start("http://*:2000/"); //Start AppSelfHost 

     appHost.Resolve<FrontendMessages>().Start(); //Start timer 

     Process.Start("http://localhost:2000/"); //View in Web browser 
     Console.ReadLine(); //Prevent Console App from existing 
    } 
} 
+0

デミスありがとう、今それは期待どおりに動作します:)ありがとう、タイマーのヒント。 –

関連する問題