2011-02-07 5 views
0

私はチャットを作成しようとしていますが、基本的に私はどのスレッドを呼び出す関数を使用しました。
私はサーバーが私に送るものを読むことができますが、私は一度だけ書くことができます。私はこれを完了しようとしているが、サーバーに書き込む方法がわからない場合は、サーバ:
(これは前にコンソールアプリケーションフォームに書いてあり、サーバは正常に動作しています...つまり、 。Winforms、Invokes、問題のあるボタン

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     Button btn1 = new Button(); 
     btn1.Click += button1_Click; 
    } 
    StreamReader sr; 
    StreamWriter sw; 
    TcpClient connection; 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     connection = new TcpClient("127.0.0.1", 5000); 
     sr = new StreamReader(connection.GetStream()); 
     sw = new StreamWriter(connection.GetStream()); 

    } 

    private void button2_Click(object sender, EventArgs e) 
    { 

     Thread t2 = new Thread(Reader); 
     t2.Start(connection); 
    } 

    string msg; 
    public void Reader(object o) 
    { 

     TcpClient con = o as TcpClient; 
     if (con == null) 
      return; 
     while (true) 
     { 
      msg = sr.ReadLine(); 

      Invoke(new Action(Output)); 
     } 
    } 

    public void Output() 
    { 
     ChatScreen.Text = msg;//set the message on the screen 
    } 
    string textinput; 

    private void button1_Click(object sender, EventArgs e) 
    { 
     textinput = InputLine.Text; 
     sw.WriteLine(textinput);// this thing, writes once, multiple clicks wont send a new line to the server :(..the problem is in this button 
     sw.Flush(); 

    } 


} 

私は何を思ったことは、複数回クリック..eg btn.Click()を行うことができるようになりますので、ボタンを接続するために..ですかWriteLineメソッドの呼び出しでスレッドを実行します(ただし、私の直感は述べていますボタンを数回クリックするとプログラムが動作するようになります

+0

と話題にし、起こっ(およびデバッグ出力ウィンドウに印刷された)いずれかの例外がありますか? – Timbo

+0

私は自分のコードを1ヶ月前のものにリセットしましたが、今は動作します。私はアプリケーションを閉じるときに、invokeメソッドで例外が発生します。それは普通ですか? –

+0

私が持っている別の問題は、どのように私はwinformsでプライベートメッセージングを作成することができますです。サイドバーに表示されるラベルやボタンを作成したいときは、そのボタンをクリックするとウィンドウが開き、そのメンバーとしかチャットできません!! –

答えて

1

フォームを閉じるときにスレッドプロセスを停止する必要があります。呼び出しを実行しようとしないと、フォームが破棄されて失敗するdisposeメソッドをオーバーライドしてリーダースレッドを停止させるか、oncloseメソッドで実行することができます。または、リーダープロセスが使用可能かどうかチェックすることができます(未処理です)。利用できない場合は、読み取りプロセスを終了します。

エラーを防ぐために、リーダープロセスが複数回起動されないようにする必要があります。そのため、スレッドの実行時にボタンを無効にする必要があります。

編集は:

あなたは複数の行を読み取るために、あなたがフォームを閉じると、スレッドを停止するには、次のコードのようなものを使用することができます。

private bool mbIsRunning = true; 

    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     lock (this) 
     { 
     mbIsRunning= false; 
     } 
    } 

    private bool IsRunning 
    { 
     get 
     { 
      lock(this) 
      { 
       return mbIsRunning; 
      } 
     } 
    } 


    string msg; 
    public void Reader(object o) 
    { 

     TcpClient con = o as TcpClient; 
     if (con == null) 
      return; 
     while (IsRunning) 
     { 
      msg = reader.ReadLine(); 
      string line; 
      while((line = reader.ReadLine()) != null) 
      { 
       msg = msg + Enviroment.NewLine + line; 
      } 

      Invoke(new Action(Output)); 
     } 
    } 
+0

また、私は持っているrichTextBoxに送られた後に、各メッセージの後で新しい行を始めるのに問題があります。\ nまたは\ r ,,しかしdidntヘルプを実行しようとしました –

+0

新しい行Environment.NewLineを使用する必要があります。しかし、私はあなたのコードで新しい行を挿入することができますが、あなたはmsgboxに読み込まれたテキストを含めるときにそれを行う必要があります(しかし、私はあなたが読んだテキストを連結しているのを見ることはできません)。 – Borja

+0

sw1 [i] .WriteLine(name [i] + ":" + word2、Environment.NewLine);それは私がやったことです。例外を呼び出すのを防ぐ方法とスレッドを停止する方法を教えてください。 –

0

コードを実行すると、TcpClientが例外をスローするなどのエラーが発生します。 しかし、すべてのコードを投稿していないと仮定すると、try ... catch関数のすべてをキャッチし、catchのブレークポイントを使用して問題の内容を確認することをおすすめします。例外を調べる - 例外は例外的な状況でのみスローされるべきです - そうすれば、あなたのコードは本当に動作するはずです。

+0

スレッドを止めるにはどうしたらいいですか?私は試して、呼び出しの周りにキャッチする必要がありますか?漁獲物の中で何をするのですか? –

+0

はい、試してみてください...呼び出しの周りをキャッチします。実行時にキャッチ結果を無視するだけで、例外がどこに行きたくないのかはわかりませんが、デバッグ時には何がうまくいかないかに関する情報を与える例外の詳細を見ることができます。 – Manicguitarist

0

私は自分のサーバーコードの連結を実行します。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net; 
using System.Net.Sockets; 
using System.IO; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      TcpListener server = new TcpListener(IPAddress.Any, 5000); 
      server.Start(); 
      Console.WriteLine("Server started"); 
      string word = ""; 
      savedObject saved = new savedObject(); 

      while (true) 
      { 
       TcpClient connection = server.AcceptTcpClient(); 
       Console.WriteLine("connection accepted"); 
       ThreadPool.QueueUserWorkItem(saved.ProssecClient, connection); 
      } 
     } 
    } 
} 





class savedObject 
{ 
    Dictionary<string, StreamWriter> dic = new Dictionary<string, StreamWriter>(); 
    StreamReader[] sr1 = new StreamReader[100]; 
    StreamWriter[] sw1 = new StreamWriter[100]; 
    string[] name = new string[100]; 
    int m; 
    int a; 
    int g; 
    string word; 

    public string AllWords(string sit) 
    { 
     word += sit + " ";// here i concat them 
     return word; 
    } 


    public string word2() 
    { 
     return word; 
    } 



    public void ProssecClient(object o) 
    { 


     TcpClient connection = o as TcpClient; 
     if (connection == null) 
     { 
      return; 
     } 
     StreamReader sr = new StreamReader(connection.GetStream()); 
     StreamWriter sw = new StreamWriter(connection.GetStream()); 
     sr1[a++] = new StreamReader(connection.GetStream()); 
     sw1[m++] = new StreamWriter(connection.GetStream()); 
     string word2 = ""; 
     sw.WriteLine("Please, fill your name: "); 
     name[g++] = sr.ReadLine(); 

     if (name[g] != null && sw1[m] != null) 
     { 
      dic.Add(name[g], sw1[m]); 
     } 
     try 
     { 
      while (true) 
      { 
       int i = 0; 
       word2 = AllWords(sr.ReadLine()); 

       for (i = 0; i < 3; i++) 
       { 
        if (sw1[i] != null) 
        { 
         sw1[i].WriteLine(name[i] + ": " + word2);// here is the words that are sent.. 

         sw1[i].Flush(); 

        } 

       } 

      } 
     } 
     catch { Console.WriteLine("client left"); } 
    } 

} 
+0

クライアントでは、1行ずつ読み込んでいますので、クライアント側で異なる行を連結する必要があります(前のコメントで述べたように)。しかし、この問題だけがありますか? "ProssecClient"はチェックなしでコレクションインデックスを使用し、forインデックスも一般的にコードが明確ではないため、 "dic"の使用法がわかりません。理由は0〜図3の例では、メンバ「a」、「m」、「g」のいずれも使用されていない。 – Borja

+0

私はプライベートメッセージを使うときにdicの使い方が使われるようになります。私はストリームと名前を辞書に保存する必要があります。 a mとgは単なる数字であり、配列内のスペースを数えます。私はすべてのストリームと名前を配列に保存するので、すべてのメッセージにメッセージを送ることができます。私はなぜ私は新しい行を開始するコマンドでメッセージを送信することはできません理解していない:(またはクライアント側でそれを行う単純に各メッセージが到着した後に行を中断する..しかし、私はそれを行うことはできません –

関連する問題