Question

I am new to async programming and to WP8 , this is my first app and I have some issues with Dispatcher.BeginInvoke(..)

In my code behind the view class, i am trying to load data in a Pivot scree async for the second tab.

Here is what i have right now :

public partial class ReminderPivot : PhoneApplicationPage
    {
        #region Reminder Members
        private ReminderViewModel _model;
        private IRepository _repository;
        #endregion Reminder Members

        #region Constructors
        public ReminderPivot()
        {
            InitializeComponent();
            _model = new ReminderViewModel();
            _repository = new LocalStorageRepository();

            LoadData();
            LoadAsyncData();

            this.DataContext = _model;

        }
        #endregion Constructors

        public void LoadData()
        {
            IEnumerable<Reminder> activeList = _repository.GetRemindersByStatusId(2);
            if (activeList != null)
            {
                foreach (var reminder in activeList)
                {
                    _model.ActiveReminders.Add(reminder);
                }
            }
        }
        public void LoadAsyncData()
        {            
            Action action = () =>
            {
                Thread.Sleep(5000);

                IEnumerable<Reminder> inactiveList = _repository.GetRemindersByStatusId(3);
                if (inactiveList != null)
                {
                    _model.InctiveReminders = new System.Collections.ObjectModel.ObservableCollection<Reminder>(inactiveList);
                }
            };

           Dispatcher.BeginInvoke(action);
        }

The thing is that this STILL blocks my UI thread. What am i missing here?

EDIT : The idea is to load data async into the ViewModel ObservableCollection wich is ModelBinded in the XAML.

If i try to make the call async on another thread with Task.Factory(...) etc lets say, this crashes as i am changing the binding from another thread not UI thread.

Was it helpful?

Solution

After the suggestion of @PedroLamas i made it work, not sure if this is the nicest way or the most elegant but it gets the job done.

Im making the call that takes time to complete on another thread with Task.Factory and making it awaitable, and at the end just update the UI with the Dispatcher.

public async void LoadAsyncDataWithTask()
        {
            IEnumerable<Reminder> inactiveList = null;
            Action action = () =>
            {
                Thread.Sleep(2000);
                inactiveList = _repository.GetRemindersByStatusId(2);
            };

            await Task.Factory.StartNew(action);

            Action action2 = () =>
            {
                if (inactiveList != null)
                {
                    foreach(var item in inactiveList)
                    {
                        _model.InctiveReminders.Add(item);
                    }
                }
            };

            Dispatcher.BeginInvoke(action2);

        }

OTHER TIPS

While what you've found works and using Task is very up-to-date, by using Thread.Sleep you're still blocking a thread in the ThreadPool for no good reason.

You can avoid this by using a one-off System.Threading.Timer (see MSDN reference) which will fire on one of the (background) ThreadPool threads. Then use a Dispatcher.BeginInvoke(...) at the end of your timer callback to update the UI.

For example:

        var timer = new System.Threading.Timer(
            state =>
                {
                    // ... your code to run in background

                    // ... call BeginInvoke() when done
                    Dispatcher.BeginInvoke(() => MessageBox.Show("done"));
                },
            null,
            5000,
            System.Threading.Timeout.Infinite);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top