Async execution

17 views
Skip to first unread message

Gerhard Kreuzer

unread,
Feb 18, 2011, 3:15:25 AM2/18/11
to nro...@googlegroups.com
Hi,
 
just have to deal with some little problem.
 
I want to run some actions within a background thread, and show progress in the UI and finally ececute a navigation request after the work is done.
Normally this was solved using someControl.Dispatcher.BeginInvoke(someDelegate), but in MVVM, this is little bit different. We use a background worker and data binding and NotifyPropertyChanged to post changes back. Using the NotifyProperyChanged(..) method supplied by nRoute fails, because it doesn't take care of threading, which basically is ok.
 
The point is, should I fiddle around this in some way, or perhaps is this a point, which can be included into the nRoute framework, because I am not the only one struggling over this scenario.
 
Or, is there still some solution included?
 
Thanks for helping
 
Gerhard

Adrian Hara

unread,
Feb 18, 2011, 3:36:30 AM2/18/11
to nro...@googlegroups.com

What I do is use the Reactive Extensions framework for async work and it gives you the option to have the callbacks be called on the UI thread, like so:

 

var observable = DoSomeWork(); // returns IObservable, or you can use Observable.Start()

observable.ObserveOnDispatcher().Subscribe(_ => {}, error => {}, () => {});

 

All code within {} will be called on the UI thread and there you can do the NotifyPropertyChanged safely.

 

Worked for me until now, but I’m of course open to suggestions J

 

Adi

Freundliche Grüsse / Best regards

Adrian Hara
Cloud Developer
LinkedIn 


coresystems ag
Villa im Park | Dorfstrasse 69
5210 Windisch | Switzerland


Phone +41 56 500 22 22
Fax +41 56 444 20 50
Infoline +41 848 088 088
www.coresystems.ch
www.coresuite.com
follow us on
twitter

Visit us at CeBIT:
SAP Partner Booth: Hall 5, Booth A18
Cloud Computing: Hall 4, Booth A58
OS X Business Park: Hall 2, Booth A20
Microsoft Booth: Hall 4, Booth P47

The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and / or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

John Thiriet

unread,
Feb 18, 2011, 3:47:41 AM2/18/11
to nro...@googlegroups.com
Hi,

What I do usually is that I inject the dispatcher to the viewmodel using this :

    public interface ISchedulerContext
    {
        void Schedule(System.Action action);
    }

And its implementation :

    [MapResource(typeof(ISchedulerContext), InstanceLifetime.Singleton)]
    public class DispatcherContext : ISchedulerContext
    {
        public void Schedule(System.Action action)
        {
            System.Concurrency.Scheduler.Dispatcher.Dispatcher.BeginInvoke(action);
        }
    }
And then you can use it like you use the dispatcher.

_scheduler.Schedule(InvokeMyAction)
_scheduler.Schedule(() => InvokeMyActionWithParameters(p1, p2));


Either way Adrian's trick works too, I just think it's to much code for invoking an action. No need to create an observable here for simple work.

Cheers

2011/2/18 Adrian Hara <Adria...@coresystems.ch>



--
------------------------
John Thiriet

Gerhard Kreuzer

unread,
Feb 18, 2011, 4:03:10 AM2/18/11
to nro...@googlegroups.com
Hej,
 
thanks, that is it.
Oh my god, reading about the Reactive framework and just forgot it now. Sorry.
 
With best regards
 
Gerhard


Von: nro...@googlegroups.com [mailto:nro...@googlegroups.com] Im Auftrag von Adrian Hara
Gesendet: Freitag, 18. Februar 2011 09:37
An: nro...@googlegroups.com
Betreff: RE: [nRoute] Async execution

Gerhard Kreuzer

unread,
Feb 18, 2011, 4:34:49 AM2/18/11
to nro...@googlegroups.com
Hi,
 
just found another nice thing 'Visual Studio Async CTP' and some samples at http://www.wischik.com/lu/AsyncSilverlight/AsyncSamples.html.
I think, using on board functionality, or better language integrated functionality is a more natural choice, so thanks a lot for the ideas and I will try out what this CTP is doing for me and will report here asap.
 
With best regards
 
Gerhard


Von: nro...@googlegroups.com [mailto:nro...@googlegroups.com] Im Auftrag von Adrian Hara
Gesendet: Freitag, 18. Februar 2011 09:37
An: nro...@googlegroups.com
Betreff: RE: [nRoute] Async execution

Gerhard Kreuzer

unread,
Feb 19, 2011, 9:38:18 AM2/19/11
to nro...@googlegroups.com
Hi Adrian,
 
decide to try out RX, but the framework and/or the 'documentation' is very hard to use.
 
I can start a method async, but get nothing back, so subscription works, but no method is fired or I get syntax errors, because some typ missmatch.
There were lot of so called samples but I cant find one, which is useful.
 
Here my code:

Dim

myComposer As CompositionService

myComposer = New CompositionService

Dim var = Observable.Start(Sub() myComposer.Compose()) 'Run .Compuse async, which works

var.SubscribeOnDispatcher.Subscribe(

Sub()

myLogMessages.Add(myComposer.LastMessage)

NotifyPropertyChanged(

Function() LogMessages)

End Sub,

Sub()

NavigationService.Navigate(

New NavigationRequest("Pages/AdminRoot/"))

End Sub)

And inside CompositionService, they do some strange stuff with a 'Subject', but can't find a point to use this. As the notifications were fired on that 'Subject' object, and it is never used elswere, non of my target functions were fired ....

No documentation around, so it seems, that RX is not really supportet anymore.

With best regards

Gerhard



Von: nro...@googlegroups.com [mailto:nro...@googlegroups.com] Im Auftrag von Adrian Hara
Gesendet: Freitag, 18. Februar 2011 09:37
An: nro...@googlegroups.com
Betreff: RE: [nRoute] Async execution

Gerhard Kreuzer

unread,
Feb 19, 2011, 11:38:44 AM2/19/11
to nro...@googlegroups.com
Hi,
 
so, I solved something, but can't update the content of a listbox from an async running task. I get the cross thread stuff working = I don't get the error message, but I also don't get the correct content.
I add Debug.Print's and so I can be sure, the code is running async, and the code for updateing the listbox is executed in time.
Now, whats wrong?
 
I ommit the xaml code, because databinding basically works, because I can place one entry into the list, as you can see on the screenshot, which is attached here.
 
Here the rest:
 

Public

Class ShellVM

Inherits NavigationViewModelBase

#Region

"Private Variables"

Private myInstanceId As Guid

Private myLogMessages As New List(Of String)

Private myShowLoadProgressAction As Action(Of CompositionService) = Sub(o)

myLogMessages.Add(o.LastMessage)

NotifyPropertyChanged(

Function() LogMessages)

Debug.Print("ShellVM " & myInstanceId.ToString & " -- ShowLoadProgressAction fired at " & Now.TimeOfDay.ToString)

End Sub

Private myCompositionFinishedAction As Action = Sub()

'NavigationService.Navigate(New NavigationRequest("Pages/AdminRoot/"))

Debug.Print("ShellVM " & myInstanceId.ToString & " -- CompositionFinishedAction fired at " & Now.TimeOfDay.ToString)

End Sub

#End

Region

#Region

"Constructor(s)"

Public Sub New()

myInstanceId =

Guid.NewGuid

Debug.Print("ShellVM " & myInstanceId.ToString & " -- New") 

Dim myComposer As CompositionService

myComposer =

New CompositionService

Dim var = Observable.Start(Sub() myComposer.Compose()) 'Composition scheduled to run async

Dim newsTicker = myComposer.NewsTicker

newsTicker.SubscribeOnDispatcher.Subscribe(myShowLoadProgressAction, myCompositionFinishedAction) ' Composition starts now, this line does't block UI thread

myLogMessages.Add(

"Composing ...")

NotifyPropertyChanged(

Function() LogMessages) ' just to demonstrate, that execution within the UI isn't blocked by composition

'NavigationService.Navigate(New NavigationRequest("Pages/AdminRoot/"))

End Sub

#End

Region

Public ReadOnly Property LogMessages As IEnumerable(Of String)

Get

Return myLogMessages

End Get

End Property

End

Class

And my sofisticated 'CompositionService' class:

 

Imports

System.ComponentModel

Public

Class CompositionService

#Region

"Private Variables"

Private ReadOnly mySubject As New Subject(Of CompositionService)

Private myLastMessage As String

#End

Region

Public Sub Compose()

myLastMessage =

"Three"

mySubject.OnNext(

Me)

System.Threading.

Thread.Sleep(10000)

myLastMessage =

"Two"

mySubject.OnNext(

Me)

System.Threading.

Thread.Sleep(10000)

myLastMessage =

"One"

mySubject.OnNext(

Me)

System.Threading.

Thread.Sleep(10000)

myLastMessage =

"Liftoff"

mySubject.OnNext(

Me)

System.Threading.

Thread.Sleep(100)

mySubject.OnCompleted()

End Sub

Public ReadOnly Property NewsTicker As IObservable(Of CompositionService)

Get

Return mySubject.AsObservable

End Get

End Property

Public ReadOnly Property LastMessage As String

Get

Return myLastMessage

End Get

End Property

End

Class

 

Navigation fails also, but this is another task. First I want to have a simple listbox showing something like a countdown.

The real application should place version infos, infos about loaded extension moduls and whatever there.

With best regards

Gerhard



Von: nro...@googlegroups.com [mailto:nro...@googlegroups.com] Im Auftrag von Gerhard Kreuzer
Gesendet: Samstag, 19. Februar 2011 15:38
An: nro...@googlegroups.com
Betreff: AW: [nRoute] Async execution

Async exec problems 1.JPG

Rishi Oberoi

unread,
Feb 23, 2011, 5:23:12 AM2/23/11
to nro...@googlegroups.com
Let me just throw this example of abstracting and executing something asynchronously:
    [MapService(typeof(IGenerateGameService), Lifetime = InstanceLifetime.PerInstance)]
    public class GenerateGameService : 
        BackgroundWorker, IGenerateGameService
    {
       
#region IGenerateGameService Members

        public void GenerateGame(GameLevel level, Action<Game> gameCallback)
        {
            if (gameCallback == nullthrow new ArgumentNullException("gameCallback");
            RunWorkerAsync(new GameInfo()
                           {
                               GameLevel = level, 
                               GameCallback = gameCallback
                           });
        }

#endregion

#region Overrides

        protected override void OnDoWork(DoWorkEventArgs e)
        {
            // create game
            var _gameInfo = (GameInfo)e.Argument;
            var _game = new Game() { Level = _gameInfo.GameLevel};
            _game.NewGame();
            _gameInfo.GameResult = _game;

            // and return
            e.Result = _gameInfo;
        }

        protected override void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
        {
            var _gameInfo = (GameInfo)e.Result;
            if (_gameInfo != null) _gameInfo.GameCallback(_gameInfo.GameResult);
        }

#endregion

#region Nested Class

        private class GameInfo
        {
            public GameLevel GameLevel { getset; }

            public Action<Game> GameCallback { getset; }

            public Game GameResult { getset; }
        }

#endregion

    }
}
Where IGenerateGameService is:
    public interface IGenerateGameService
    {
        void GenerateGame(GameLevel level, Action<Game> gameCallback);
    }
Abstracting like this is generally more helpful when you have a set of logic that is used in multiple places.

Cheers,
Rishi 

Adrian Hara

unread,
Feb 23, 2011, 5:27:02 AM2/23/11
to nro...@googlegroups.com

Quick question: lately I’ve been moving away from methods that take a “callback” parameter and writing them so they return an IObservable instead. I’ve found that this helps a lot in the long run if you ever need to compose multiple async calls. So far I haven’t seen an obvious flaw with this approach and can’t really think of a time when callbacks would be more appropriate. Am I missing something? J

 

Freundliche Grüsse / Best regards

Adrian Hara
Cloud Developer
LinkedIn 


coresystems ag
Villa im Park | Dorfstrasse 69
5210 Windisch | Switzerland


Phone +41 56 500 22 22
Fax +41 56 444 20 50
Infoline +41 848 088 088
www.coresystems.ch
www.coresuite.com
follow us on
twitter

Visit us at CeBIT:
SAP Partner Booth: Hall 5, Booth A18
Cloud Computing: Hall 4, Booth A58
OS X Business Park: Hall 2, Booth A20
Microsoft Booth: Hall 4, Booth P47

The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and / or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

From: nro...@googlegroups.com [mailto:nro...@googlegroups.com] On Behalf Of Rishi Oberoi


Sent: Wednesday, February 23, 2011 11:23 AM
To: nro...@googlegroups.com

Rishi Oberoi

unread,
Feb 23, 2011, 5:31:11 AM2/23/11
to nro...@googlegroups.com
You are right, retuning an IObservable generally is a better option - with the only exception being where you don't want to take an external dependency (at least in SL) on the observable library. 
Rishi
Reply all
Reply to author
Forward
0 new messages