CBreeze February 2016

Prevent Locking of UI Thread

I have a DataGrid on my main page that is full of Employees. Each Employee has an "in" status - this is modified based on whether the Employee is currently in the building or not.

I need to consistently update this DataGrid as people will be entering or leaving the building throughout the day. This means I will be sending MySQL queries somewhere between every 1-5 seconds until the user clicks on a button to navigate to another page.

I have tried the most simple and obvious solution, a While loop however this freezes and locks the UI. How can I create a loop that runs and queries MySQL without locking the UI?

EDIT: Attempted Answer

        public void PeriodicCall()
        {
            var employeeDS = new EmployeeDataService();
            int i = 1;
            Timer timer = new Timer(
                state => {
                    Employees = employeeDS.HandleEmployeeSelect();
                    FilteredView = CollectionViewSource.GetDefaultView(Employees);
                    Application.Current.Dispatcher.BeginInvoke(new Action(() => {
                        dataGrid.ItemsSource = FilteredView;
                        testLabel.Content = "Who's Who " + i;
                        i++;
                    }));
                },
                null, //no object as Callback parameter
                TimeSpan.FromSeconds(0), //start in x millisec
                TimeSpan.FromSeconds(1)); //time between call
        }

Answers


nkoniishvt February 2016

You should use a timer to periodically retrieve data from your DB and update data in your datagrid using the Dispatcher.BeginInvoke function.

Timer timer = new Timer(
    state => {
        //Callback function
        Object yourData = GetDataFromDB();
        Application.Current.Dispatcher.BeginInvoke(new Action(()=> {
            YourUIProperty = yourData;
        }));
    },
    null, //no object as Callback parameter
    TimeSpan.FromSeconds(1), //start in x millisec
    TimeSpan.FromSeconds(5) //time between call
);


javirs February 2016

You can use a Backgroundworker, hook to its .completed and there render (using

BackgroundWoker worker = new BackgroundWorker();
worker.DoWork += functioToDo
worker.Completed += functionWhere you update the UI
worker.runAsynchronous(); //actually starts the thread

In the function that updates the UI don't forget to use the dispatcher to access the UI thread:

dispatcher.invoke((Action) delegate { here your code})

to access the UI thread for elsewhere.

Other cooler approach is to take care of the propertyChanged and bind the changes to the UI. But this is a bit more complex and I don't know the details by head.

You can use a timer to start the whole thing every few seconds.

A third approach would be to have a trigger when you update the data base. We would need more details to know how to attach there. But from there you can also call some updates in the UI and then you don't need to use CPU to check every seconds (you know, work by interruption instead of by polling).

Post Status

Asked in February 2016
Viewed 2,860 times
Voted 6
Answered 2 times

Search




Leave an answer