2017-04-10 3 views
1

私はボットでサーバーと通信するためにWebソケットを使用しようとしています。しかし、実行時にSystem.NullReferenceExceptionがスローされます。私は別のスレッドでバックグラウンドでソケットを実行しているので、ボットと干渉することはありません。ソケット、Null参照例外

私はWebsocketSharpライブラリを使用しています。

最初のメッセージは正常ですが、2番目のメッセージではHumanCollaboratorDialogクラスの次の行で例外がスローされます。

await context.PostAsync(e.Data); 

マイソケットストリームクラスは以下の通りである:

public static class SocketStream 
{ 
    public static WebSocket ws; 
    private static List<string> serverMsg = new List<string>(); 

    public static void initializeSocket() 
    { 

     ws = new WebSocket("ws://Some IP:8080/human-collaborator/data"); 
     Debug.WriteLine("****** INITIALIZED SOCKET (should happen only once) *****"); 
     Task.Run(() => startSocketStream()); 

    } 

    private static void startSocketStream() 
    { 
     int attempts = 0; 
     while (!ws.IsAlive) 
     { 
      try 
      { 
       attempts++; 
       ws.Connect(); 
      } 
      catch (WebSocketException) 
      { 

       Debug.WriteLine("Connection attempts: " + attempts.ToString()); 
      } 

     } 

     ws.OnOpen += (sender, args) => 
     { 
      Debug.WriteLine("# SOCKET OPENED"); 

     }; 

     ws.OnError += (sender, args) => 
     { 
      Debug.WriteLine("# SOME ERROR OCCURED"); 
     }; 

     ws.OnClose += (sender, args) => 
     { 
      Debug.WriteLine("# SOCKET CLOSED"); 

     }; 
    } 
} 

私は、アプリケーション・レベル

public class WebApiApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     GlobalConfiguration.Configure(WebApiConfig.Register); 
     SocketStream.initializeSocket(); 

    } 
} 

マイHumanCollaboratorDialogクラスでそれを実行するためにGlobal.asxでinitializeSocket()メソッドを呼び出しています

[Serializable] 
public class HumanCollaboratorDialog : IDialog<object> 
{ 

    public async Task StartAsync(IDialogContext context) 
    { 

     context.Wait(this.MessageReceivedAsync); 

    } 

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result) 
    { 

     var message = await result; 

     SocketStream.ws.OnMessage += async (sender, e) => 
     { 
      try 
      { 
       await context.PostAsync(e.Data); 
      } 
      catch (HttpRequestException ex) 
      { 
       throw ex; 
      } 
     }; 

      Thread.Sleep(500); 
      string output = message.Text; 
      SocketStream.ws.Send(output); 
      Thread.Sleep(500); 

     context.Wait(MessageReceivedAsync); 

    } 
} 

私MessagesControllerは、POSTメソッドを次のようしています

public virtual async Task<HttpResponseMessage> Post([FromBody]Activity activity) 
    { 
     if (activity.Type == ActivityTypes.Message) 
     { 
      await Conversation.SendAsync(activity,() => new HumanCollaboratorDialog()); 
     } 
     else 
     { 
      HandleSystemMessage(activity); 
     } 
     var response = Request.CreateResponse(HttpStatusCode.OK); 
     return response; 
    } 

Neithet e.Dataもコンテキストが空です。私は問題がソケット接続であると思うか、私はSocketStreamクラスで何か間違ったことをしている可能性があります。画像がされ、次の

Exception-Image enter image description here

+0

なぜWeb APIでソケットを実行しているのか分かりません... –

+0

@EzequielJadibバックグラウンドでソケットを連続して実行したいので、サーバ上で何か変更があった場合、ボットに通知できます。このシナリオでは、より良い解決策は何ですか? –

+2

脇の下には、 'catch(Exception ex){throw ex; } '。 [それは悪です](http://stackoverflow.com/questions/881473/why-catch-and-rethrow-an-exception-in-c) – Default

答えて

1

あなたのボットは、Webサービスです。メッセージは、クライアント(Webページ、アプリケーション、別のサービスなど)によってサービスに送信され、MessagesControllerのPostメソッドで受信されます。あなたがしようとしていることのためにソケットコードをサーバ上に持つ必要はありません。 Webソケットは、直接回線接続を介してボットからクライアント上のメッセージを受信するのに便利です。


ボットフレームワークのダイレクトラインクライアントを使用し、Webソケット接続を作成する例です。ウェブソケットが会話のStreamUrlから作成されている様子がわかります

DirectLineClientCredentials creds = new DirectLineClientCredentials(directLineSecret); 
DirectLineClient directLineClient = new DirectLineClient(creds); 
Conversation conversation = await directLineClient.Conversations.StartConversationAsync(); 

using (var webSocketClient = new WebSocket(conversation.StreamUrl)) 
{ 
    webSocketClient.OnMessage += WebSocketClient_OnMessage; 
    webSocketClient.Connect(); 
    while (true) 

    { 
     string input = Console.ReadLine().Trim(); 

     if (input.ToLower() == "exit") 
     { 
      break; 
     } 
     else 
     { 
      if (input.Length > 0) 
      { 
       Activity userMessage = new Activity 
       { 
        From = new ChannelAccount(fromUser), 
        Text = input, 
        Type = ActivityTypes.Message 
       }; 

       await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, userMessage); 
      } 
     } 
    } 
} 
private static void WebSocketClient_OnMessage(object sender, MessageEventArgs e) 
{ 
    // avoid null reference exception when no data received 
    if (string.IsNullOrWhiteSpace(e.Data)) 
    { 
     return; 
    } 

    var activitySet = JsonConvert.DeserializeObject<ActivitySet>(e.Data); 
    var activities = from x in activitySet.Activities 
         where x.From.Id == botId 
         select x; 

    foreach (Activity activity in activities) 
    { 
     Console.WriteLine(activity.Text); 
    } 
} 

これは、ボットと通信するためのダイレクトラインを使用しているコンソールアプリケーションからのものであり、ここではウェブソケットを使用してメッセージを待機している: https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-DirectLineWebSockets