locked
Async Methods are failing to run concurrently RRS feed

  • Question

  • Hi,

    I have written following three async methods

    PlaySoundAsync - Plays a sound
    ReadFileAsync - Reads an xml file from Assets directory
    DisplayContentAsync - Binds the list of data to Listview

    Isue is coming while calling DisplayContentAsync method. Can you please advise me how to run this three async methods concurrently so that individual thread can execute them. It seems like sound is not playing properly while binding the data in listview.

    Sample Project files are shared in following location

    http://www.4shared.com/zip/IuUfbI1N/SampleWin8App.html

    Help appreciated!


    Thanks
    Subhendu DE - Visit My Blog If a post answers your question, please click Mark As Answer on that post. If you find a post helpful, please click Vote as Helpful.

    Saturday, August 10, 2013 7:32 AM

Answers

  • Here is a simple way to execute them concurrently.

    public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            public async Task<IList<Employee>> ReadFileAsync()
            {
                var _file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Sample.xml"));
                var _reader = await Windows.Storage.FileIO.ReadTextAsync(_file);
    
                XDocument _doc = null;
    
                using (StringReader _xml = new StringReader(_reader))
                {
                    _doc = XDocument.Load(_xml);
                }
    
                IEnumerable<Employee> _employees = from _employee in _doc.Descendants("EMPLOYEE")
                                                   select new Employee()
                                                  {
                                                      Name = _employee.Element("NAME").Value,
                                                      Age = _employee.Element("AGE").Value,
                                                      Country = _employee.Element("COUNTRY").Value,
                                                  };
    
                return _employees.ToList<Employee>();
            }
    
            public async Task DisplayContentAsync(IList<Employee> _employees)
            {
                Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                               () => { lvDataTemplates.ItemsSource = _employees; });
            }
    
            public async Task PlaySoundAsync()
            {
                Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                    async() =>
                                        {
                                            MediaElement _sound = new MediaElement();
                                            var _file =
                                                await
                                                StorageFile.GetFileFromApplicationUriAsync(
                                                    new Uri("ms-appx:///Assets/JIRA.wav"));
                                            var stream = await _file.OpenAsync(FileAccessMode.Read);
                                            _sound.SetSource(stream, _file.ContentType);
                                            _sound.Play();
                                        });
    
            }
    
            protected async override void OnNavigatedTo(NavigationEventArgs e)
            {
                PlaySoundAsync();
                ReadFileAsync().ContinueWith((completedTask) => { DisplayContentAsync(completedTask.Result); });
            }
        }
     

    - Ram
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Saturday, August 10, 2013 8:13 AM
  • Hi Subhendu,

    Sorry for the delay in response. Here is the problem(i guess), as both the Media element and the action of assigning item source to ListView are executed in the UI thread, the media element is stopped when the itemsource update is triggered.

    So a simple fix could be, assign the data source first and then play the media element after a delay like shown below

    public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            public async Task<IList<Employee>> ReadFileAsync()
            {            
                var _file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Sample.xml")); 
                var _reader = await FileIO.ReadTextAsync(_file);
    
                XDocument _doc = null;
    
                using (StringReader _xml = new StringReader(_reader))
                {
                    _doc = XDocument.Load(_xml);
                }
    
                IEnumerable<Employee> _employees = from _employee in _doc.Descendants("EMPLOYEE")                                 
                                      select new Employee()
                                     {
                                         Name = _employee.Element("NAME").Value,
                                         Age = _employee.Element("AGE").Value,
                                         Country = _employee.Element("COUNTRY").Value,
                                     };
    
                return _employees.ToList<Employee>();
            }
    
            public async Task DisplayContentAsync(IList<Employee> _employees)
            {
                Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() =>
                    {
                        lvDataTemplates.ItemsSource = _employees;
                        await Task.Delay(100);// Change this number to whatever you want
                        await PlaySoundAsync();
                    });
            }
    
            public async Task PlaySoundAsync()
            {
                
                                        MediaElement _sound = new MediaElement();
                                        var _file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/JIRA.wav"));
                                        var stream = await _file.OpenAsync(FileAccessMode.Read);
                                        _sound.SetSource(stream, _file.ContentType);
                                        _sound.Play();
                                   
            }
    
            protected async override void OnNavigatedTo(NavigationEventArgs e)
            {
                var resultList = await ReadFileAsync();
                await DisplayContentAsync(resultList);
            }
        }

    Background audio agent is another option, but i don't think that is needed for this simple requirement.


    - Ram
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Tuesday, August 13, 2013 11:26 AM

All replies

  • Here is a simple way to execute them concurrently.

    public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            public async Task<IList<Employee>> ReadFileAsync()
            {
                var _file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Sample.xml"));
                var _reader = await Windows.Storage.FileIO.ReadTextAsync(_file);
    
                XDocument _doc = null;
    
                using (StringReader _xml = new StringReader(_reader))
                {
                    _doc = XDocument.Load(_xml);
                }
    
                IEnumerable<Employee> _employees = from _employee in _doc.Descendants("EMPLOYEE")
                                                   select new Employee()
                                                  {
                                                      Name = _employee.Element("NAME").Value,
                                                      Age = _employee.Element("AGE").Value,
                                                      Country = _employee.Element("COUNTRY").Value,
                                                  };
    
                return _employees.ToList<Employee>();
            }
    
            public async Task DisplayContentAsync(IList<Employee> _employees)
            {
                Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                               () => { lvDataTemplates.ItemsSource = _employees; });
            }
    
            public async Task PlaySoundAsync()
            {
                Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                    async() =>
                                        {
                                            MediaElement _sound = new MediaElement();
                                            var _file =
                                                await
                                                StorageFile.GetFileFromApplicationUriAsync(
                                                    new Uri("ms-appx:///Assets/JIRA.wav"));
                                            var stream = await _file.OpenAsync(FileAccessMode.Read);
                                            _sound.SetSource(stream, _file.ContentType);
                                            _sound.Play();
                                        });
    
            }
    
            protected async override void OnNavigatedTo(NavigationEventArgs e)
            {
                PlaySoundAsync();
                ReadFileAsync().ContinueWith((completedTask) => { DisplayContentAsync(completedTask.Result); });
            }
        }
     

    - Ram
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Saturday, August 10, 2013 8:13 AM
  • Hi Ram,

    Thanks a lot for your prompt reply.

    I have followed whatever you mentioned but still no luck. Can you please check the modified code?

    Modified Project files are shared in following location

    http://www.4shared.com/zip/X3y-oJd7/SampleWin8App_1.html


    Thanks
    Subhendu DE - Visit My Blog If a post answers your question, please click Mark As Answer on that post. If you find a post helpful, please click Vote as Helpful.

    Saturday, August 10, 2013 9:43 AM
  • Try this:

    private async void ExecuteTheFollwoing()

    {

          await PlaySoundAsync();

          await ReadFileAsync();

          await DisplayContentAsync();

          //Do some other stuff;

    }

    Monday, August 12, 2013 1:47 PM
  • Hi Subhendu,

    Sorry for the delay in response. Here is the problem(i guess), as both the Media element and the action of assigning item source to ListView are executed in the UI thread, the media element is stopped when the itemsource update is triggered.

    So a simple fix could be, assign the data source first and then play the media element after a delay like shown below

    public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            public async Task<IList<Employee>> ReadFileAsync()
            {            
                var _file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Sample.xml")); 
                var _reader = await FileIO.ReadTextAsync(_file);
    
                XDocument _doc = null;
    
                using (StringReader _xml = new StringReader(_reader))
                {
                    _doc = XDocument.Load(_xml);
                }
    
                IEnumerable<Employee> _employees = from _employee in _doc.Descendants("EMPLOYEE")                                 
                                      select new Employee()
                                     {
                                         Name = _employee.Element("NAME").Value,
                                         Age = _employee.Element("AGE").Value,
                                         Country = _employee.Element("COUNTRY").Value,
                                     };
    
                return _employees.ToList<Employee>();
            }
    
            public async Task DisplayContentAsync(IList<Employee> _employees)
            {
                Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() =>
                    {
                        lvDataTemplates.ItemsSource = _employees;
                        await Task.Delay(100);// Change this number to whatever you want
                        await PlaySoundAsync();
                    });
            }
    
            public async Task PlaySoundAsync()
            {
                
                                        MediaElement _sound = new MediaElement();
                                        var _file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/JIRA.wav"));
                                        var stream = await _file.OpenAsync(FileAccessMode.Read);
                                        _sound.SetSource(stream, _file.ContentType);
                                        _sound.Play();
                                   
            }
    
            protected async override void OnNavigatedTo(NavigationEventArgs e)
            {
                var resultList = await ReadFileAsync();
                await DisplayContentAsync(resultList);
            }
        }

    Background audio agent is another option, but i don't think that is needed for this simple requirement.


    - Ram
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Tuesday, August 13, 2013 11:26 AM