Persist layouts in background via new Thread/Task

3 posts, 1 answers
  1. Johannes
    Johannes avatar
    66 posts
    Member since:
    Dec 2012

    Posted 27 Mar 2015 Link to this post

    I want the layouts of some of my RadControls to be persisted in background via a new Thread/Task. The corresponding method is invoked so I can access the control that should be persisted without any error. But I'm always getting an exception at the time I call PersistenceManager.Save(control). Here's my code:

    // --- Part of CustomRadGradView.cs (inherits from RadGridView) ---
     
    // Save this RadGridViews layout in background
    Task.Run(() =>
        {
            using (var manager = new CustomPersistenceManager())
            {
                // this is current RadGridView
                manager.SaveLayout(this, file);
            }
        }
    }


    // --- Part of CustomPersistenceManager.cs (inherits from PersistenceManager) ---
     
    // save layout of any Telerik control
    public bool SaveLayout(Control control, string file = null)
    {
        // Current thread has no access to control -> Invoke required
        if (control.Dispatcher.CheckAccess() == false)
        {
            bool result = false;
            Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => result = DoSaveLayout(control, file)));
            return result;
        }
     
        // Current thread has access to control
        return DoSaveLayout(control, file);
    }
     
    // save layout to stream
    private bool DoSaveLayout(Control control, string file = null)
    {
        // this lines work without any errors so method is invoked correctly; thread has access to control!
        string name = control.Name; // returns name of control
        control.Name = "New name"; // just for testing
     
        // Next line always throws an InvalidOperationException
        using (var stream = Save(control)) // call save method of Teleriks PersistenceManager class
        {
            stream.Seek(0, SeekOrigin.Begin);
     
            using (var reader = new StreamReader(stream))
            {
                string text = reader.ReadToEnd();
                File.WriteAllText(path, text);
            }
        }
    }


    Can you please provide help why PersistenceManager.Save method is always throwing an exception here? How to use PersistenceManager to save a layout in background/new Task?
  2. Answer
    Kiril Vandov
    Admin
    Kiril Vandov avatar
    324 posts

    Posted 31 Mar 2015 Link to this post

    Hello Johannes,

    In order to save data to using the RadPersistenceFramework you just need to call simply its Save() method, you can find more information about in this article. However in your case you are getting InvalidOperation Exception "The calling thread cannot access this object because a different thread owns it" as you are creating the PersistanceManager in one thread and use try to use it from another. You can easily solve this issue if you move the Dispatcher logic directly after calling the Task:
    Task.Run(()=>
    {
        if (this.invisibleButton.Dispatcher.CheckAccess() == false)
        {
            Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
            {
                using (var provider = new CustomPersistenceManager())
                {
                    provider.SaveLayout(this.invisibleButton, file);
                }
            }));
        }
    });
    and remove the logic from the SaveLayout.

    I hope this information helps.

    Kind regards,
    Kiril Vandov
    Telerik
     

    See What's Next in App Development. Register for TelerikNEXT.

     
  3. UI for WPF is Visual Studio 2017 Ready
  4. Johannes
    Johannes avatar
    66 posts
    Member since:
    Dec 2012

    Posted 01 Apr 2015 in reply to Kiril Vandov Link to this post

    Okay I see my mistake. Thank you very much for your help - now it works fine.
Back to Top