2015-05-20 85 views
8

我一直在嘗試使用SignalR,它非常整潔。基本上我想達到的是:SignalR - 發送消息OnConnected

一旦設備連接它應該發送一條消息到第一個。如果有超過1個連接的設備,我想發送兩條消息。一個到所有,但最後連接的客戶端爲。還有一條消息,只有上次連接的客戶端。

當我將它放在一個自定義的API控制器中並且基本上調用該操作時,我一直使用的代碼很完美,但那不是我想要的。

我想在沒有任何用戶交互的情況下,儘快在OnConnected之內連接設備時發送消息,但是當我將代碼放入OnConnected覆蓋範圍內時,它將停止工作。它不再發送給特定客戶端(首先連接並且最後連接)。

我希望有人能夠幫助我解決這個問題,因爲我現在一直在敲我的頭幾個小時。

public override System.Threading.Tasks.Task OnConnected() 
    { 
     UserHandler.ConnectedIds.Add(Context.ConnectionId, UserHandler.ConnectedIds.Count + 1); 

     int amountOfConnections = UserHandler.ConnectedIds.Count; 
     var lastConnection = UserHandler.ConnectedIds.OrderBy(x => x.Value).LastOrDefault(); 
     var allExceptLast = UserHandler.ConnectedIds.Take(amountOfConnections - 1).Select(x => x.Key).ToList(); 

     if (amountOfConnections == 1) 
     { 
      Clients.Client(UserHandler.ConnectedIds.First().Key).hello("Send to only(also first) one"); 
     } 
     else 
     { 
      Clients.Clients(allExceptLast).hello("Send to everyone except last"); 
      Clients.Client(lastConnection.Key).hello("Send to only the last one"); 
     } 

     return base.OnConnected(); 
    } 

回答

4

感謝所有幫助(upvoted你們)。其實發現問題..它在我的客戶端。我首先訂閱了'hello'函數,之後我開始了HubConnection。只要我改變這個命令,一切正常。

它曾與下面的客戶端代碼:

private async Task ConnectToSignalR() 
    { 
     var hubConnection = new HubConnection("url"); 
     hubConnection.Headers["x-zumo-application"] = "clientapikey"; 

     IHubProxy proxy = hubConnection.CreateHubProxy("ChatHub"); 

     proxy.On<string>("hello", async (msg) => 
     { 
      Console.WriteLine(msg); 
     }); 

     await hubConnection.Start(); 
    } 
1

嗯......你是返回一個任務...所以我認爲可能是問題... 應先執行你的代碼,然後返回任務......或把ContinueWith。 ..喜歡...

public override Task OnConnected() 
    { 
     Task task = new Task(() => 
      { 
       UserHandler.ConnectedIds.Add(Context.ConnectionId, UserHandler.ConnectedIds.Count + 1); 

       int amountOfConnections = UserHandler.ConnectedIds.Count; 
       var lastConnection = UserHandler.ConnectedIds.OrderBy(x => x.Value).LastOrDefault(); 
       var allExceptLast = UserHandler.ConnectedIds.Take(amountOfConnections - 1).Select(x => x.Key).ToList(); 

       if (amountOfConnections == 1) 
       { 
        Clients.Client(UserHandler.ConnectedIds.First().Key).hello("Send to only(also first) one"); 
       } 
       else 
       { 
        Clients.Clients(allExceptLast).hello("Send to everyone except last"); 
        Clients.Client(lastConnection.Key).hello("Send to only the last one"); 
       } 
      }); 

     task.ContinueWith(base.OnConnected()); 

     return task; 
    } 

我沒有測試過這...它只是一個猜測..

3

因爲我們還沒有建立連線,試圖調用內的客戶端.hello()功能OnConnected在這一點上是不可能的。但是,我們可以定義一個服務器集線器方法,並立即調用我們的連接.done回調。然後,在我們的新服務器方法中,我們可以重新分配您當前在OnConnected中使用的邏輯。

這將改變我們的設置頗有幾分引入一些額外的步驟,但要遵循下面的例子...

// WhateverHub 
public override Task OnConnected() 
{ 
    return base.OnConnected() 
} 

public void AfterConnected() 
{ 
    // if(stuff) -- whatever if/else first user/last user logic 
    // { 
     Clients.Caller.hello("message") 
    // } 
} 

var proxy= $.connection.whateverHub; 

proxy.client.hello = function(message) { 
    // last step in event chain 
} 

$.connection.hub.start().done(function() { 
    proxy.server.afterConnected() // call AfterConnected() on hub 
}); 

所以這裏的基本思路是先

  1. 連接=>.done(function() { ... });
  2. 呼叫server.afterConnected()
  3. 該方法
  4. 內執行邏輯如果我們滿意的條件調用我們.hello()客戶端功能

注意 - 這個實現是一個JavaScript客戶端 - 但同樣的想法可以被翻譯成.net客戶端。這主要是一個架構問題。

10

除非我錯過了你的問題的東西,解決方案看起來很簡單對我來說,你只需要切換到使用

Clients.Caller.hello("Send to only the last one"); 

,而不是試圖瞭解自己誰是最後的連接ID。同爲其他的,你可以使用:

Clients.Others.hello("Send to everyone except last"); 

你並不需要所有的邏輯,你的設置,那些2線做你的需要,而且他們內部OnConnected工作。

+0

非常感謝這個代碼。它實際上使我的代碼更容易! – Mittchel