プロが教えるわが家の防犯対策術!

C#でGUIを作成して、WEBサーバー上のPHPで作った簡易APIにPOSTしてサーバー側に
データを溜め込みそれをC#のGUI側で随時表示という、いわばGUIのチャットをつくっています。まず、GUIをつくりGUI上のフォームからテキストを入力してサーバー側のPHPへPOSTしログとしてためることはできましたが、どうもGUI側で連続ポスト・・・大体い1~2秒に一度ポストすると、三度目のポストでGUIがフリーズしています。ただしアプリが落ちるわけでなく、POST完了にずいぶん時間がかかっているらしく一分ぐらいするとPOSTが完了してフリーズも直ります。このパターンが続きます。
つまり、3の倍数の回数目のPOSTのみフリーズするのです。なんとか、これを解消して
問題なく連続POSTができるようにしたいのです。お力添え願います。ソースは以下になります。
using System;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Web;
using System.Net;
using System.Text;

public class MainClass{

public static void Main(string [] args){

NewForm formObj = new NewForm(500,500);
formObj.SetTitle("チャットアプリサンプル");
Application.EnableVisualStyles();
Application.Run(formObj);
}
}

public class NewForm : Form{

//Formに付加するコントロールオブジェクト
public Label labelObj =new Label();
public Button buttonObj =new Button();
public TextBox boxObj =new TextBox();
public TextBox responseBox =new TextBox();
public UserRequest user;
public NewForm( int localWidth,int localHeight){
this.Width = localWidth;
this.Height = localHeight;
this.boxObj.Width = localWidth/2;
this.boxObj.Height = localHeight/2;
this.boxObj.Multiline =true;
this.boxObj.Location = new Point(50,200);
this.responseBox.Width =300;
this.responseBox.Height =150;
this.responseBox.Multiline =true;
this.Controls.Add(this.responseBox);
this.buttonObj.Text ="サーバーへ送信";
this.buttonObj.Width =150;
this.buttonObj.Height =50;
this.buttonObj.Location =new Point(350,10);
this.buttonObj.Click += new EventHandler(this.ClickMethod);
this.Controls.Add(this.boxObj);
this.Controls.Add(this.buttonObj);
this.user = new UserRequest("http://localhost/csharp.php");
}
public void SetTitle(String titleText){
this.Text = titleText;
}
public void ClickMethod(Object sender , EventArgs e){
this.user.SetUrlPath("http://localhost/csharp.php");
this.user.SetPostData(this.boxObj.Text,"POST");
this.user.SendData();
this.boxObj.Text = "";
this.user.DeleteStream();
}
}
//通信用クラスの定義
public class UserRequest{
//HTTPリクエストオブジェクト
private HttpWebRequest http;
//通信先のURL
private string path = "";
//通信先URLへとPOSTするpostdata
private string postData ="";
//通信のメソッドタイプ
private string method ="POST";
//contenttypeの指定
private string ct = "application/x-www-form-urlencoded";
//送信データの文字列のurlエンコードを行う。
private Encoding encode = Encoding.GetEncoding("UTF-8");
//postデータをバイト型配列に
private byte [] postDataBytes;
//実際にpostデータを送受信するためのStreamを用意しておく
private Stream reqStream;
private Stream resStream;
/*
この辺は、迷っています。独自クラスのUserRequestというクラスのコンストラクタで
HttpWebRequestのオブジェクトをつくってやるか
それとも、オブジェクト作成のためだけのメソッドを定義してやるか・・・。
public UserRequest(string httpPath){
//this.path = httpPath;
//httpオブジェクトの作成
//this.http =(HttpWebRequest) WebRequest .Create(this.path);
}
public void SetUrlPath (string setUrlpathData){
this.path = setUrlpathData;
this.http =(HttpWebRequest) WebRequest .Create(this.path);
}
*/
//postDataのセット
public void SetPostData (string postDataParam,string methodType){
//ポストデータをUrlエンコードしアスキー文字にまとめる。
this.postData = "messageData=" + HttpUtility.UrlEncode(postDataParam,this.encode);
//postDataをバイト配列型に格納する。
this.postDataBytes = Encoding.ASCII.GetBytes(this.postData);
this.method = methodType;

//HTTPオブジェクトにそれぞれの値を設定する。
this.http.ContentType = this.ct;
this.http.Method = this.method;
this.http.ContentLength = this.postDataBytes.Length;
}
public void SendData (){
try{
using(this.reqStream = http.GetRequestStream()){
this.reqStream.Write(this.postDataBytes,0,this.postDataBytes.Length);
this.reqStream.Close();
}
}catch(Exception e){
MessageBox.Show(e.ToString());
}
}
public void DeleteStream(){
this.http = null;
this.reqStream = null;
}
}
PHPとかjsは仕事でつかっているのですが
C#見たく、完全なOOPを扱うのは初めてなので
うまいユーザー定義のクラスではないかもしれません。

A 回答 (2件)

UIスレッドで時間のかかる処理を行うことをやってはいけません。


時間がかかるならば非同期処理を行う必要があります。

・.NET 4.5~の場合
async/awaitを使うのが簡単でしょう。
コンパイラが頑張ってステートマシンを作ってくれて,処理のほとんどをUIスレッドで処理を実行してくれます。
# かつ,Networkアクセスは非同期
http://msdn.microsoft.com/ja-jp/library/hh156513
http://msdn.microsoft.com/ja-jp/library/system.n …

・.NET 2.0~の場合
本来なら,以下の.NET 1.0~の場合と同じ方法がよいのですが,
UI弄るのが面倒なので,BackgroundWorkerを使うのが簡単です。
# .NET 4.0だとRxという解もあるけれども省略。
http://msdn.microsoft.com/ja-jp/library/system.c …

・.NET 1.0~の場合
WebRequest.BeginGetResponseとWebRequest.EndGetResponseを使ったパターンを使うことになります。
UI弄るのは面倒ですが,Control.Invokeを使ってUIスレッドで実行するように書く必要があります。
http://msdn.microsoft.com/ja-jp/library/system.n …
http://msdn.microsoft.com/ja-jp/library/zyzhdc6b
    • good
    • 0
この回答へのお礼

GUIとは別に、WEBサーバー側へ
データをPOSTする処理だけThreadクラスを用いて別スレッドとして処理しました。

>UI弄るのは面倒ですが,Control.Invokeを使ってUIスレッドで実行するように書く必要があります。

というのは、メインスレッド上のフォーム要素に別スレッドから何かしらメインスレッド上のフォームにアクセスする場合に用いれるものですね。

面倒なときは、別スレッドで実行するデリゲートの中身をまるっとControls.Invoke()で
ラップしてやるといいんですね。

本来はInvokeRequiredで
ちゃんと条件わけしてやるのがよいのでしょうけど「・・・。

お礼日時:2012/10/22 22:38

Webサーバー等にリクエストを出した時には,


たいていレスポンスが返ってくるまで,時間がかかってくるものだと思うから
ある程度のフリーズは,やむを得ないと思いますし,

高速にリクエストを出し続けたら,サーバー側が耐えられなくなるんじゃないですかね.


とにかく連続して出したいなら,
マルチスレッドにするか,
もしかしたら,

HttpWebRequestのProxy プロパティをnullに設定すると,
多少改善するかも.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!