2

このコードでボタンのテキストを変更する最初の試行が機能しないのに 3 回目の試行は機能するのはなぜですか?

ユーザーは、シリアル ポートが接続されるまで数秒待つ必要があります。その後、私は彼がすでに接続していることを彼に警告したいと思います (2 回目の試行は問題を引き起こす可能性があります)。

彼が「当たり前」と思って 2 回クリックしないように、大丈夫だということを知らせたかったのです。

失敗。テキストの変更は表示されません。

では、ボタン テキストの 3 番目の変更は機能するのに、最初の変更は機能しないのはなぜですか? 2番目が機能するかどうかはわかりません。

 /***********************************************************************
  * Button:  Connect Port                                               *
  ***********************************************************************/

 private void TheConnectPortButton_Click(object sender, EventArgs e) 
 {
     string OldText = TheConnectPortButton.Text;

     TheConnectPortButton.Text = "Busy, Please Wait";  /////// This never happens

     ButtonBoss.ButtonHandler_ConnectPort();

     TheConnectPortButton.Text = OldText;              /////// Not sure if this happens

     if (aUartSemaphoreThatTells.IfWeHaveConnectedToAPort == (int)aValueWhichIndicatesThat.YesWeHaveAGoodPortConnected)
     {
         TheConnectPortButton.Text = "Connected";      /////// This one does happen
     }

 }

これは、他のボタン ルーチン (たとえば、Tx/Rx などの前に接続されていることを確認する) と一緒に、彼が 2 回目に接続しないようにするためaUartSemaphoreThatTells.IfWeHaveConnectedToAPortにルーチンによっても使用されます。ButtonBoss

ルーチンがこのように戻った後、コードを変更してみました...

    if (aUartSemaphoreThatTells.IfWeHaveConnectedToAPort == (int)aValueWhichIndicatesThat.YesWeHaveAGoodPortConnected)
    {
        TheConnectPortButton.Text = "Connected";
    }
    else
    {
        TheConnectPortButton.Text = OldText;
    }

...そして、それでも同じ結果が得られます。

私の推測では (これだけです)、スレッド化が何らかの形でこれらすべてに関与しており、シリアル ポート ルーチンがボタン テキスト変更ルーチンに打ち勝っており、現時点では適切にフォローしていません。

質問: 接続がシステムを占有する前に、テキストを変更するにはどうすればよいですか?

(そんなことがあったら)

質問 2: これを実現できない場合は、ボタンを「グレー表示」することについて読んだことがあると思います。または、実際にユーザーの目の前でボタンを非表示にできることをどこかで見たと思います。再度クリックすることはできません。サンプルコードへのリンクは大歓迎です。

4

1 に答える 1

2

問題は、結果として同じイベント ハンドラーからすべてを実行しているため、ボタンを更新 (再描画) する時間がないことです。メソッドを呼び出すこともできますがApplication.DoEvents();、まったくお勧めできません。Application.DoEvents() の使用をお読みください。

通常、時間のかかるタスクを別のスレッドにプッシュし、そこから進捗レポートを取得し、GUI を更新することが期待されていると思います。「ワーカー」スレッドを作成し、そこから応答を得る方法はたくさんあります。たとえば、BackgroundWorker クラスを使用します。

public partial class Form1 : Form
{
    public Form1() { InitializeComponent(); }

    private void button1_Click(object sender, EventArgs e)
    {
        BackgroundWorker w = new BackgroundWorker();
        w.WorkerReportsProgress = true;
        w.DoWork += new DoWorkEventHandler(w_DoWork);
        w.ProgressChanged += new ProgressChangedEventHandler(w_ProgressChanged);
        w.RunWorkerCompleted += new RunWorkerCompletedEventHandler(w_RunWorkerCompleted);
        w.RunWorkerAsync();
        button1.Text = "Started";
    }

    //may influence GUI, as this event handler is run on the GUI thread
    void w_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        button1.Text = "Job is done";
    }
    //may influence GUI, as this event handler is run on the GUI thread
    void w_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        button1.Text = e.ProgressPercentage.ToString();
    }
    //runs in the worker thread...should do the actual job
    //may influence GUI through `ReportProgress`
    //or through `Invoke` method
    void w_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        for (int i = 1; i <= 10; i++)
        {
            Thread.Sleep(500);
            worker.ReportProgress(10 * i);
        }
    }
}

または、Task Classを使用することもできます:

public partial class Form1 : Form
{
    public Form1() { InitializeComponent(); }

    private void button1_Click(object sender, EventArgs e)
    {
        new Task(DoTask).Start();
    }

    void DoTask()
    {
        for (int i = 1; i <= 10; i++)
        {
            Thread.Sleep(500);
            //here you need to update GUI through `Invoke` method
            //as the GUI may only be influenced from the the thread,
            //where it's created
            this.Invoke(new Action<int>((j) =>
                {
                    button1.Text = j.ToString();
                }), 10 * i);
        }
    }
}
于 2013-01-10T00:56:37.157 に答える