Jesse Myers
Jesse Myers

Reputation: 69

UI button running on separate thread?

my issue is the following:

1.I have an intensive method which updates GUI element (chart) in a while loop

2.I need to break out of this loop when a button is pressed.

3.Problem is the button event handler doesn't get executed until the while loop is finished.

4.I've tried running the method on separate thread but that is very problematic since it sets and reads many UI elements, pretty much I couldn't get that to work, so I'm hoping of there being a way to run just the stop button on a separate thread and update a global variable which let's me break out of the loop.

Any Idea how that can be accomplished?

private void playBack(int playTime, int runUntil)
        {
            var frameTime = new DateTime(); var frameTime_ = new DateTime();

            bool fwd = true;
            if (runUntil < playTime) fwd = false;

            playTime = trPlay.Value;

            playGoStop = true;

            lbPlayTime.Text = (playTime * numDtStepSize.Value).ToString();

            while (true) //trPlay.Maximum + 1)
            {
                frameTime = DateTime.UtcNow;
                if ((frameTime - frameTime_).TotalMilliseconds > (double)(1000 / numFps.Value))
                {
                    systemUpdate(playTime);
                    trPlay.Value = playTime;
                    trPlay.Update();

                    lbPlayTime.Update();


                    frameTime_ = frameTime;
                    if (fwd)
                    {
                        playTime++;
                        if (playTime > runUntil) break;
                    }
                    else
                    {
                        playTime--;
                        if (playTime < runUntil) break;
                    }
                }
                if (!playGoStop) break;
            }
        }

Upvotes: 2

Views: 791

Answers (2)

AechoLiu
AechoLiu

Reputation: 18408

In your while loop, you can call Application.DoEvents(). It will fetch UI events from event queue, and process those events. Then, your button events will be processed.

You can search by the keyword Application.DoEvents() and C#. There are many topics about it.

UPDATE:

In your codes, it is a infinite while loop inside. I don't like to run a infinite in main thread. I will prefer to run it in a worker-thread. And send message to do UI updates in main-thread. Generally, UI events needs to be processed in the main-thread.

If the infinite while loop is already in the worker-thread, it should sleep about 5~10 ms per loop, in order to free CPU resources to process some events in the other threads.

Upvotes: 1

GEEF
GEEF

Reputation: 1185

You should look at binding your UI element (chart) data to a DependencyProperty. This allows you to run the intensive method on a non-UI thread, allowing your UI thread to be responsive to button clicks. While on the background thread, simply make Dispatcher.BeginInvoke() calls to update your DependencyProperty (as it can only be updated from the UI thread) and this will update your control bound to it.

As far as your button interrupt goes, a simple solution is to set a flag from your UI which is checked within each loop iteration. A more complex solution would be to run this intensive method in a task Task, giving it CancellationTokenSource, then cancel the source upon button click.

Upvotes: 0

Related Questions