0

プログラムに大量のテキストを投稿させようとしています。ユーザーは、テキスト、メッセージの量、およびメッセージの配信速度を入力します。プログラムがビジー状態の場合、ボタンのテキストは「開始」ではなく「停止」にする必要があります。最初に起動した後にボタンを押して強制的に停止すると、テキストは「開始」に戻りますが、コードが適切であり、エラーを生成しません。

これは、何らかの理由でテキストが更新されていないためだと感じています。Invalidate() と Update() でフラッシュしようとしましたが、うまくいきません。これを修正する方法は?

コードは次のとおりです。

private void button1_Click(object sender, EventArgs e)
    {
        if (button1.Text == "Start")
        {
            isEvil = true;
            button1.Text = "Stop";

            Thread t = new Thread(StartTyping);
            t.Start(textBox1.Text);
        }
        else
        {
            isEvil = false;
            button1.Text = "Start";
        }
    }

    private void StartTyping(object obj)
    {
        string message = obj.ToString();
        int amount = (int)numericUpDown2.Value;
        Thread.Sleep(3000);


        for (int i = 0; i < amount; i++)
        {
            if (isEvil == false)
            {
                //////This does NOT work
                //button1.Text = "Start";
                //button1.Invalidate();
                //button1.Update();
                //button1.Refresh();
                //Application.DoEvents();
                break;
            }

            SendKeys.SendWait(message + "{ENTER}");
            int j = (int)numericUpDown1.Value * 10;
            Thread.Sleep(j);
        }
    }
4

5 に答える 5

2

UIスレッドからUIのものを更新するように指示する4つの回答がありますが、コードのロジックフローの問題に対処するものはありません.

発生しない理由は、 for ループでis の場合にのみ発生するためisEvilですfalseisEvilに設定されるのはいつfalseですか? 「停止」をクリックしたときのみ、それ以外の場所ではありません。

スレッドの終了後に「停止」をクリックせずにボタンを「開始」に戻す場合は、ループの後にコードを追加して、 :の値とは無関係にそれを行う必要がありisEvilます (VoidMain の回答を便乗)。

private void StartTyping(object obj)
{
    string message = obj.ToString();
    int amount = (int)numericUpDown2.Value;
    Thread.Sleep(3000);

    for (int i = 0; i < amount; i++)
    {
        if (isEvil == false)
        {
            if (button1.InvokeRequired)
            {
                button1.BeginInvoke( new Action(() => { button1.Text = "Start"; }) );
            }
            else
            {
                button1.Text = "Start";
            }
            break;
        }

        SendKeys.SendWait(message + "{ENTER}");
        int j = (int)numericUpDown1.Value * 10;
        Thread.Sleep(j);
    }

    if (button1.InvokeRequired)
    {
        button1.BeginInvoke( new Action(() => { button1.Text = "Start"; }) );
    }
    else
    {
        button1.Text = "Start";
    }
}

コードが重複しているため、別のメソッドに分割することをお勧めします。

于 2012-09-26T22:31:09.627 に答える
0

UI を更新するには、UI スレッドにいる必要があります。

SynchronizationContextと呼ばれるものを試してください。ググってみると例がたくさん出てきます。

WPFまたはSilverlightを使用している場合は、 Dispatcherを使用できます。繰り返しになりますが、これらのキーワードを google または StackOverflow で検索すると、多くの例が見つかります。

于 2012-09-26T21:58:59.263 に答える
0

UI スレッドからコントロールを更新する必要があります。これは、winforms に対して行う方法です。

    for (int i = 0; i < amount; i++)
    {
        if (isEvil == false)
        {
            button1.Invoke(new Action(() => button1.Text = "Start"));
            break;
        }

        SendKeys.SendWait(message + "{ENTER}");
        int j = (int)numericUpDown1.Value * 10;
        Thread.Sleep(j);
    }

これは、button1 のテキストが更新されるまでブロックされます。ブロックしたくない場合は、に置き換えInvokeますBeginInvoke

于 2012-09-26T22:00:52.613 に答える
0

このようなもの(テストされていません)が動作するはずです:

private void StartTyping(object obj)
{
    string message = obj.ToString();
    int amount = (int)numericUpDown2.Value;
    Thread.Sleep(3000);


    for (int i = 0; i < amount; i++)
    {
        if (isEvil == false)
        {
            if(button1.InvokeRequired)
            {
                button1.BeginInvoke( new Action(() => { button1.Text = "Start"; }) );
            }
            else
            {
                button1.Text = "Start";
            }
            break;
        }

        SendKeys.SendWait(message + "{ENTER}");
        int j = (int)numericUpDown1.Value * 10;
        Thread.Sleep(j);
    }
}
于 2012-09-26T22:02:56.153 に答える
0

あなたの最善の策は、BackgroundWorkerを使用することです。ここに簡潔な例を追加するのは少し面倒ですが、O'Reilly の適切なチュートリアルがあります。

于 2012-09-26T22:15:49.167 に答える