Async Fetch Calls

Async Fetch Calls

Old forum URL: forums.lhotka.net/forums/t/4871.aspx


FireGarden posted on Tuesday, May 20, 2008

I am sure this question has been asked before. I have found this thread offered some help:
http://forums.lhotka.net/forums/thread/10752.aspx

My question is simply how do we make the web requests for sending CSLA accross the portal async?

I have attempted to use the background worker for the static GET fetch but it always returns the error:

The calling thread cannot access this object because a different thread owns it.

Given the amount of time and energy put into Csla it would seem there should be a simple way to make all network calls async.

Any direction is much appreciated. Thank you,

Rob FireGarden

RockfordLhotka replied on Tuesday, May 20, 2008

You can use the BackgroundWorker component from Windows Forms or WPF to make async calls. But all the normal multi-threading concerns apply.

The error you are getting typically occurs because you have code on a background thread that is trying to interact with UI elements. That is not allowed, and Windows Forms/WPF throw that exception to help you avoid disaster.

So what you need to watch for is that a callback or completion event may be on a background thread. The BackgroundWorker handles this for you - but only if you use it correctly. You can never interact with UI elements in the actual work method - you can only interact with the UI in the progress or complete event handlers because those are on the UI thread.

FireGarden replied on Tuesday, May 20, 2008

Thank you Rocky for taking the time to address my question. I believe I am making the calls correctly. The following is an excerpt of my code perhaps there is something obvious I am missing here.

        public void GetAsync()
        {
            _backgroundWorker = new BackgroundWorker();
            _backgroundWorker.DoWork += new DoWorkEventHandler(GetAsync_DoWork);
            _backgroundWorker.RunWorkerCompleted += new          RunWorkerCompletedEventHandler(GetAsync_RunWorkerCompleted);           
            _backgroundWorker.RunWorkerAsync();
        }
        void GetAsync_DoWork(object sender, DoWorkEventArgs e)
        {          
            e.Result = Business.Countries.Get();                      
        }

        void GetAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _countryList = (Countries)e.Result;
            RaiseEvent(GetCompleted);
        }

The error message occurs when I try to assign _countryList to a property of the UI. I should mention I am using a self referencing MVP implementation where the control implementats IView and creates a  presenter which is passed in an IModel. Eg. constructor of IView as follows:

        public CountryRegionPanel() : IView
        {        
            new CountryRegionPresenter(this, CountryFactory.New());           
        }

Thank you,

Rob FireGarden

RockfordLhotka replied on Tuesday, May 20, 2008

Hmm, that code does look fine at a glance anyway.

 

I think you need to use the debugger – put a breakpoint at the top of GetAsync() and check the thread (you can show the Threads window in the debugger to easily see what’s running on what thread). Then put a breakpoint in your completed event handler and ensure the thread is the same. Then I’d step through that raiseevent and follow it to where the data binding source is set – it sure seems like something must be switching you to a different thread in there somewhere…

 

Rocky

FireGarden replied on Tuesday, May 20, 2008

The problem was realated to me using the constructor of my window rather than the window loaded event to initialze my MVP triad / M being the CSLA BO. This is not the first time using a windows constructor has caused an unknown threading issue. Please be aware using WindowLoaded seems to lead to more consistent results.

public MainWindow()
{
    this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{

this.Content = new Main.MainCanvas(new Main.MainModel(), new    DecorSoftViewFactory());
}

Thank you,

Rob Firegarden

==============
www.firegarden.com

RockfordLhotka replied on Tuesday, May 20, 2008

Ahh, yes. This is an even more common and bigger issue in WPF – avoid the constructor if at all possible!

 

Rocky

 

Copyright (c) Marimer LLC