1

I want to change wpf controls status after click button start.

The picture is what I want.

what I want

Following is my code

private bool _bWorking = false;
public delegate void UpdateStatusDelegate();

private void SetStatus(bool bEnable)
{
    if (bEnable)
    {
        tbName.IsReadOnly = false;
        barStatus.Visibility = Visibility.Hidden;
        btnStart.IsEnabled = true;
        btnStop.IsEnabled = false;
        btnClose.IsEnabled = true;
    }
    else
    {
        tbName.IsReadOnly = true;
        barStatus.Visibility = Visibility.Visible;
        btnStart.IsEnabled = false;
        btnStop.IsEnabled = true;
        btnClose.IsEnabled = false;
    }
}

internal void UpdateStatus()
{
   SetStatus(true);
   _bWorking = false;
}

private void ThreadFunc()
{
    //for (; ; )
    //{
    //    // do something here
    //    if (_bWorking == false)
    //        break;
    //}
    Thread.Sleep(500);
    this.Dispatcher.Invoke(new UpdateStatusDelegate(UpdateStatus));
}

private void btnStart_Click(object sender, RoutedEventArgs e)
{
    _bWorking = true;
    SetStatus(false);
    this.UpdateLayout();//this.InvalidateVisual();
    try
    {
        Thread t = new Thread(new ThreadStart(() =>
        {
            ThreadFunc();
        }));
        t.IsBackground = true;
        t.Name = "test status";
        t.Start();

        while (t.IsAlive)
        {
            // wait thread exit
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }        
}

private void btnStop_Click(object sender, RoutedEventArgs e)
{
    _bWorking = false;
    SetStatus(true);
}

But actually after I click button start, the UI seems frozen, and the thread exited, the UI become normal.

my VS is VS2010.

Force a WPF control to refresh?

this post is not work for me.

edit summary:

add delegate void UpdateStatusDelegate() and function UpdateStatus() to my code

Community
  • 1
  • 1
Rock
  • 205
  • 1
  • 4
  • 14
  • possible duplicate of [How to update the GUI from another thread in C#?](http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c) – Gusdor Jan 09 '14 at 16:05
  • Thanks, but it is not work for me. That post talked about WinForm, my problem is about WPF. – Rock Jan 14 '14 at 04:05

3 Answers3

3

// wait thread exit

The whole point of a background thread is to not wait for it by blocking your UI thread. Don't.

Instead, have the thread notify your UI when it's done.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • But you want to change your UI after the thread is done. If you *wait* for the thread, you don't need a thread, you could just do this without a second thread. You don't want to *wait*, you want your thread to notify your UI when it can do those things that you want to do when the thread is done. – nvoigt Jan 09 '14 at 14:11
  • I add delegate void UpdateStatusDelegate() and function UpdateStatus(). It is still not work. – Rock Jan 14 '14 at 04:35
  • 1
    @Rock You still have your busy wait loop. Drop the waiting for the thread. – nvoigt Jan 14 '14 at 06:06
  • I still cannot click stop button. – Rock Jan 15 '14 at 03:17
  • I use Stopwatch to simulate jobs. It works now. Thanks. – Rock Jan 15 '14 at 11:51
0

Try to use BackgroundWorker component it might help you. For more information check the MSDN article

Lukas Kubis
  • 929
  • 5
  • 17
0

workable code

    public delegate void UpdateStatusDelegate();
    private bool _bWorking = false;

    private void SetStatus(bool bEnable)
    {
        if (bEnable)
        {
            tbName.IsReadOnly = false;
            barStatus.Visibility = Visibility.Hidden;
            btnStart.IsEnabled = true;
            btnStop.IsEnabled = false;
            btnClose.IsEnabled = true;
        }
        else
        {
            tbName.IsReadOnly = true;
            barStatus.Visibility = Visibility.Visible;
            btnStart.IsEnabled = false;
            btnStop.IsEnabled = true;
            btnClose.IsEnabled = false;
        }
    }

    internal void UpdateStatus()
    {
        SetStatus(true);
    }

    private void ThreadFunc()
    {
        try
        {
            // use Stopwatch to simulate jobs
            var watch = Stopwatch.StartNew();
            for (; ; )
            {
                var elapsedMs = watch.ElapsedMilliseconds;
                if (elapsedMs > 10000 // 10 seconds
                    || _bWorking == false)
                {
                    break;
                }
            }
            watch.Stop();
            this.Dispatcher.Invoke(new UpdateStatusDelegate(UpdateStatus));
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        _bWorking = false;
    }

    private void btnStart_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            _bWorking = true;
            SetStatus(false);
            Thread t = new Thread(new ThreadStart(() =>
            {
                ThreadFunc();
            }));
            t.IsBackground = true;
            t.Name = "test status";
            t.Start();
            //while (t.IsAlive)
            {
                // wait thread exit
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void btnStop_Click(object sender, RoutedEventArgs e)
    {
        _bWorking = false;
        SetStatus(true);
    }
Rock
  • 205
  • 1
  • 4
  • 14