0

大学の課題として、単純なマルチスレッドのServer\Clientゲームを実装しました。

メインスレッドに加えて、クライアント側には次のものがあります。

1-フォーム上の遊び場とプレーヤーの描画を担当するスレッド。

サーバーと通信して道順を送信し、場所やその他の情報を受信する2スレッド。

最初はinvokeテクニックを使用しましたが、廃棄後にグラフィックを使用していたため、機能しませんでした。別のスレッドでフォームに描画するを参照してください

したがって、これを回避して描画スレッドを正規化するために、描画スレッドで特定の時間ごとにフラグ「無効化」を発生させ、実際の処理をメインスレッドに任せます。

    public Form1()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        InitializeComponent();
    }

    private void Draw()
    {
        while (true)
        {
            Thread.Sleep(200);
            Invalidate();
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        if (map.hasGraph)
        {
            map.Draw(e.Graphics);
            if (this.Index != null)
                e.Graphics.FillRectangle(Brush, Rectangle);
            if (OpponentIndex != null)
                e.Graphics.FillRectangle(OpponentBrush, OpponentRectangle);
        }
    }

ここでの問題は、ダブルバッファリングを使用しているのにフォームが任意に点滅し、描画スレッドのスリープ時間を長くすると点滅が少なくなるということですが、200msはもう多すぎると思います。何かアドバイス?

[編集]

コードとプロパティエディタからダブルバッファリングフラグを設定していることに気付きました(これはばかげた考えかもしれません)が、フラグの1つと両方を使用してコードをテストするのに30分を費やしました、2つの場所からダブルバッファリングフラグを設定したときに発生した問題、私の問題は解決しましたが、これがそれを解決したのかどうかを知る必要があります。

4

3 に答える 3

2

それが正しく実行されるほど、それはますます悪化する必要がありますか?

プログラムがペイントするたびに、描画を起動します。これには無限ループがあり、ペイントを呼び出します。これは、別の無限ループで描画を呼び出します。ここに循環参照があるようです。Map.DrawがprivatevoidDraw()であると仮定できる場合

これにははるかに簡単な解決策があります。すべてをビットマップに描画してから、onPaintイベントでビットマップを描画します。

Bitmap buffer=new Bitmap(this.Width, this.Height); //make sure to resize the bitmap during the Form.Onresize event
Form1()
{
    InitializeComponent();
    Timer timer=new Timer();
    timer.Interval= 100;
    timer.Tick+=......
    timer.Start()
}

//the Timer tick event
private void timer_tick(....
{
    if (map.hasGraph)
    {
         using (Graphics g = Graphics.FromImage(buffer))
        {
            //You might need to clear the Bitmap first, and apply a backfround color or image
            //change color to whatever you want, or don't use this line at all, I don't know
            g.Clear(Color.AliceBlue);

            if (this.Index != null)
                g.FillRectangle(Brush, Rectangle);
            if (OpponentIndex != null)
                g.FillRectangle(OpponentBrush, OpponentRectangle);
        }
     panel1.BackgroundImage=buffer;
     }
}

構文の正確さについてこれをテストしなかったことに注意してください。

于 2012-06-01T11:16:48.393 に答える
0

実行された操作に対して、システムのメモリが非常に少ない可能性があります。それについてもっと読む。 http://msdn.microsoft.com/en-us/library/system.drawing.graphics.aspx

于 2012-06-01T11:14:32.660 に答える
0
  1. 最後にレンダリングされたシーンを保存するために使用されるイメージを作成します。
  2. 画像に描画する新しいスレッドを作成します
  3. 画像を更新するタイマーを作成する
  4. タイマーティックで画像をフォームにコピー
于 2012-06-01T11:57:11.643 に答える