0

メモリ ゲーム用の C# コードを作成しようとしています。最初にマトリックス(3つの要素を持つ)をビューアに表示し、次に各要素のいくつかのオプションを表示して、一度にそのセルを強調表示したいと思います。ユーザーは回答パネルから正しい要素を選択する必要があります。表示回答マトリックス (タスクとして定義) がこれを行います。表示応答タスクの for ループにメッセージ ボックスを配置すると、出力シーケンス (最初に表示される各要素の表示マトリックス、表示応答など) が正常に機能します。回答が表示されるたびにクリックして、次を待ちます。それは正常に動作します。しかし、メッセージボックスを削除すると(クリックする必要がないため)、回答が表示された後にプログラムが停止します(最初の要素の場合)。関連するコード部分は次のとおりです。

Mainform{
......declare number of textboxes and lables...for matrix display
}
 In the Buttonclick from the main form:
{
var firstTask = new Task(() => invokedisplaymatrix(MatrixInfoValues));

var secondTask = firstTask.ContinueWith((t) => invokedisplayblankmatrix(MatrixInfoValues));

var thirdTask = secondTask.ContinueWith((t) =>invokedisplayanswermatrix(MatrixInfoValues));

var fourthTask = thirdTask.ContinueWith((t) => invokedDoselection(MatrixInfoValues));

            firstTask.Start();
}
  private void invokedisplaymatrix(object Minfo1)
        {
            lock (this)
            {
                Invoke(new displaymatrixdelegate(displaymatrix), new object[] { Minfo1 });
                Thread.Sleep(2000);
            }

        }

        private void invokedisplayblankmatrix(object Minfo2)
        {
            lock (this)
            {
                Invoke(new displayblankmatrixdelegate(displayblankmatrix), new object[] { Minfo2 });
            }

        }

        private void invokedisplayanswermatrix(object Minfo3)
        {

            lock (this)
            {
                Invoke(new displayanswermatrixdelegate(displayanswermatrix), new object[] { Minfo3 });
                // Invoke(new displaymatrixdelegate(displaymatrix),new object[] {indx});
            }
        }
..Then in the display answer matrix function:

 public void displayanswermatrix(int[] Minfo3)

        {
 foreach (int ind in FilledTextBoxID2)

            {
                foreach (Control c in splitContainer1.Panel1.Controls)
                {
                    if (c is TextBox && c != null)
                    {
                        if ((boxindexL + 1) == FilledTextBoxID2[j])
                        {
                            c.BackColor = Color.OrangeRed;

                        }
                        else
                        {
                            c.BackColor = Color.MediumSpringGreen;
                        }
                       boxindexL = boxindexL + 1;
                    }

                }

                int AnswerLocation = RandomNumber(1, 5);
                int[] answeroptions=excludenumberfromarray(MatrixValues2[j]); //write a function to make random numbers between 1 and 9 excluding MatrixValues2[j]

                foreach (Control c in splitContainer1.Panel2.Controls)
                {
                    if (c is TextBox)
                    {

                        //c.Text = Convert.ToString(boxindexR);
                            //answeroptions[boxindexR]);
                        if ((boxindexR + 1) == AnswerLocation)
                        {
                            c.Text = Convert.ToString(MatrixValues2[j]); //boxindexR = boxindexR - 1;
                        }
                        else
                        {
                            c.Text = Convert.ToString(answeroptions[boxindexR]);
                        }
                       //
                       //}//placing the required number in the randomly selected box
                       boxindexR = boxindexR + 1;
                    }
                 }


                Thread.Sleep(2000);
               MessageBox.Show("hello after one number");
 j = j + 1;
                boxindexR = 0; boxindexL = 0;
            }//end of first foreach

        }//display answer matrix end

メッセージ ボックスにコメントすると、最初の要素が表示された後、インターフェイスがそこでスリープします。このエラーがどのように発生するかを教えてください。

4

1 に答える 1

0

UI スレッドでスリープすることは決して良い考えではありません。プログラムが応答しないとマークするだけです。UI は、メソッドが終了するまでペイント要求などのサービスを利用できるようにすることはできませんが、(2 秒間何度もスリープすることによって) メソッドはそれを許可していません。使用法がコードメッセージループの外で再描画を強制していると思われるMessageBoxので、機能していますが、間違った理由で機能しています。

基本的に、遅延や一時停止がある場合は、それを処理するべきではありません。Sleep何らかの形式のTimer. これにより、2 秒間スリープするのではなく、2 秒でコールバックを取得できますが、(重要なことに) その間、アプリは実際にメッセージ キューに応答できます。つまり、アプリ自体が描画されます。

でも!単純に に切り替えるとTimer、最初の「何かを開始する」呼び出しが最初のイメージをセットアップする間、数ミリ秒しか続かないため、継続としてこれらのことを行うことはできません。

結論: 必要なのは, とコールバック ( / )Taskだけである場合、多くの空想などを使用して自分自身を賢く使いこなしました:TimerTickElapsed

- is there any more of X to do? 
  - yes: do (a single) X
  - no: is there any more of Y to do? 
    - yes: do (a single) Y
    - no: is there any more of Z to do?
      - yes: do (a single) Z
      - no: stop timer
于 2012-06-07T06:20:43.680 に答える