Blog Archive

Monday, December 29, 2014

Calling Win32 DLL from 64-bit WPF through ATL 32-bit Surrogate COM

(1) How to tell if a DLL is 32-bit or 64-bit

 dumpbin /headers MyServer.dll to tell by file Header x86 or x64

(2) Run 32-Bit COM in surrogate Procese so can be called from 64-bit WPF.(one kind of IPC)
       http://www.gfi.com/blog/32bit-object-64bit-environment/ 


 
  • Locate your COM object GUID under the HKey_Classes_Root\Wow6432Node\CLSID\[GUID]
  • Once located add a new REG_SZ (string) Value. Name should be AppID and data should be the same COM object GUID you have just searched for
  • Add a new key under HKey_Classes_Root\Wow6432Node\AppID\ The new key should be called the same as the com object GUID
  • Under the new key you just added, add a new REG_SZ (string) Value, and call it DllSurrogate. Leave the value empty
  • Create a new Key under HKey_Local_Machine\Software\Classes\AppID\ Again the new key should be called the same as the COM object’s GUID. No values are necessary to be added under this key.
  • (3) Step-by-step ALT 32-bit COM Creation (check to make sure project properties are x86) http://msdn.microsoft.com/en-us/library/dssw0ch4%28d=printer,v=vs.90%29.aspx http://msdn.microsoft.com/en-us/library/9yb4317s.aspx Note that C# COM is not usable in (2), especially HKey_Classes_Root\Wow6432Node\CLSID\[GUID] is not there. Also each build of ATL COM project will override this location and need to add back AppID={Guid} (4) A good overall review of 64-bit calling 32-bit using IPC http://blog.mattmags.com/2007/06/30/accessing-32-bit-dlls-from-64-bit-code/ (5) Dynamic Loading Win32 DLL to access its functions: #pragma hdrstop #pragma package(smart_init) // CObject1 HINSTANCE hMWXUSB=0; typedef int (__cdecl *MYPROC)(LPWSTR); typedef unsigned char (ACCEPT_LED)(int data); ACCEPT_LED *lpacceptled; typedef unsigned char (OPEN_USB)(void); OPEN_USB *lpopenusb; STDMETHODIMP CObject1::get_GetANum(SHORT* pVal) { hMWXUSB=LoadLibrary(L"MWXUSB.DLL"); MYPROC Accept_LED; //Accept_LED = (MYPROC) GetProcAddress(hMWXUSB, "Accept_LED"); if( (hMWXUSB = LoadLibrary(L"MWXUSB.DLL")) == NULL ) { *pVal=-5; return S_OK; } if( (lpopenusb=(OPEN_USB*)GetProcAddress(hMWXUSB,"Open_USB" ))==NULL ) { *pVal=-6; return S_OK; } unsigned char ucOpen; ucOpen = (*lpopenusb)(); if( (lpacceptled=(ACCEPT_LED*)GetProcAddress(hMWXUSB,"Accept_LED" ))==NULL ) { *pVal=-1105; return S_OK; } unsigned char ch; ch = (*lpacceptled)(1); if(ch) { *pVal=-2105; return S_OK; } *pVal=105; return S_OK; }

    Saturday, December 27, 2014

    Call 3rd party DLL from ATL COM

    (1) use tool to generate def and .lib from DLL ( assuming no header file)
        http://purefractalsolutions.com/show.php?a=utils/expdef
    
    (2) VC++ project linker-->input additional dependency
    
    (3) declare and use in CPP
    
    extern "C"   unsigned char Open_USB();
    extern "C"   unsigned char Accept_LED(int value);
    extern "C"  void Set_Callback(void* pAny);
    
    void(__stdcall*p)(int);  // calling convention matching far pascal, for most c function
    
    //void __cdecl* p;  // ptrAny
    
    
    static void __stdcall CB1(int value)  {..} instance function would hast this->* so callback must use static to remove this.
    
     p = &CB1;
     ::Open_USB();
     ::Accept_LED(0);
     ::Set_Callback(p);
    
    again cannot use __cdecl must use __stdcall. It turns out Calling Conversion even affect [DllImport] when re-target .net 4.0 from .net 4.0, must specify CDecl in DllImports
    

    Thursday, December 25, 2014

    Manually add Connection Point support after ATL Simple object wizard already run

    After running ATL COM Simple object wizard without check "Connection Points", manual steps are need to add this support.
    
    (1) myserver.h---IConnectionPointContainer/Impl, COM_MAP, IEvents
    
    #include "ATLProject1_i.h"
    #include "_IMyServerEvents_CP.h"
    
    
    class ATL_NO_VTABLE CMyServer :
     public CComObjectRootEx<CComSingleThreadModel>,
     public CComCoClass<CMyServer, &CLSID_MyServer>,
     public IConnectionPointContainerImpl<CMyServer>,
     public CProxy_IMyServerEvents<CMyServer>,
     public IDispatchImpl<IMyServer, &IID_IMyServer, &LIBID_ATLProject1Lib, /*wMajor =*/ 1, /*wMinor =*/ 0>
    {
    
    
    BEGIN_COM_MAP(CMyServer)
     COM_INTERFACE_ENTRY(IMyServer)
     COM_INTERFACE_ENTRY(IDispatch)
     COM_INTERFACE_ENTRY(IConnectionPointContainer)
    END_COM_MAP()
    
    BEGIN_CONNECTION_POINT_MAP(CMyServer)
     CONNECTION_POINT_ENTRY(__uuidof(_IMyServerEvents))
    END_CONNECTION_POINT_MAP()
    
    (2)   .\atlproject1\atlproject1\atlproject1.vcxproj.filters -- need one include
    
        <ClInclude Include="ATLProject1_i.h">
          <Filter>Generated Files</Filter>
        </ClInclude>
        <ClInclude Include="_IMyServerEvents_CP.h">
          <Filter>Header Files</Filter>
        </ClInclude>
        <ClInclude Include="MyServer.h">
          <Filter>Header Files</Filter>
        </ClInclude>
      </ItemGroup>
    
    
    (3).\atlproject1\atlproject1\atlproject1.vcxproj --- include .h for compiler
     
    
      <ItemGroup>
        <ClInclude Include="ATLProject1_i.h" />
        <ClInclude Include="dllmain.h" />
        <ClInclude Include="MyServer.h" />
        <ClInclude Include="Resource.h" />
        <ClInclude Include="stdafx.h" />
        <ClInclude Include="targetver.h" />
        <ClInclude Include="xdlldata.h" />
        <ClInclude Include="_IMyServerEvents_CP.h" />
      </ItemGroup>
    
    
    
    (4)   .\atlproject1\atlproject1\atlproject1.idl  -- disinterface and coclass
    
    library ATLProject1Lib
    {
     importlib("stdole2.tlb");
     [
      uuid(1D071C81-6C67-458F-9B35-992DBAE162D8) // one of these are duplicate 
      uuid(118E250A-B298-4749-90D8-36C764237BA4)  
     ]
     dispinterface _IMyServerEvents
     {
      properties:
      methods:
     };
     [
      uuid(48A5B08F-ED8F-4F1F-8344-5F7C913FB895)  
     ]
     coclass MyServer
     {
      [default] interface IMyServer;
      [default, source] dispinterface _IMyServerEvents;
     };
    };
    
    
    Notes:
    (n1) to user Connection point, Add Method to _IMyServerEvents (Class View Context Menu) e.g. signature CB(int data). 
    Then Add->Connection point onto CMyServer Class (again Class View Ctx Menu) select _IMyS erverEvents in
     Source Interface List. Now there will be a function Fire_CB to fire COM Event into WPF client
    
    (n2) MyServer.rgs need update ForceRemove {dispinterface _IMyServerEvents GUI in IDL} = s 'MyServer Class'
    
    (n3) Content of  [project dir]\_IMyServerEvents_CP.h
    #pragma once
    
    using namespace ATL;
    
    template 
    class CProxy_IMyServerEvents : public IConnectionPointImpl
    {
     // WARNING: This class may be regenerated by the wizard
    public:
    };
    
    
    

    Saturday, November 29, 2014

    IDataErroInfo in MVVM +Presenter

    
    (1) MVVM INPC not compativle with Validation Event so OnPropertyChanged instead
    (2) Consider Grid Cell validation and Ok button CanExecute
    (3) IDXDataErrorInfo is for view,VM validation required custom code
    (4) IDXDataErrorInfo GetError Not implemented=> avoid clustered error on row level
    
    
          #region Validation for VM
    
            private bool _isValid;
    
            public bool IsValid
            {
                get {  return _isValid; }
                set
                {
                    if (_isValid != value)  // check to reduce chking CanExcecute
                    {
                        _isValid = value;
                        NotifyPropertyChanged(() => IsValid);
                    }
                }
            }
    
            public void Validate()
            {
                int invalidChildrenCount= Children.Count(IsChildInvalid);
                bool allDataFieldValid = Validate("Pro1") == null && Validate("Pro2") ;
                IsValid= allDataFieldValid && invalidChildrenCount= == 0;
            }
    
            private bool IsChirldInvalid(ChirldGridVMData Chirld)
            {
                
                switch (SomeMode)
                {
                    case "Mode1":
                        if (Chirld.Validdate("Prop1") != null) return true; 
                        break; 
                    ...
                }
    
                switch (Mode2)
                {
                    ...
                }
    
                return false; 
            }
    
    
    
            private string Validate(string dataFieldName)
            {
    
                switch (dataFieldName)
                {
                    case "VMProp1":
                        if (string.IsNullOrEmpty(Description))
                        {
                            return "Please enter ..."; // Non-empty description
                        }
                        break;
                  ...
                }
    
                return null;
            }
    
            public string EnsureReferenceChirldChecked()
            {
                if (Chirlds.Count(l => l.IsRefChirld.HasValue && l.IsRefChirld.Value) >= 2)
                {
                    return "Only one Chirld can be reference.";
                }
    
                if (Chirlds.Count(l => l.IsRefChirld.HasValue && l.IsRefChirld.Value) == 0)
                {
                    return "At least one Chirld must be reference.";
                }
                return null;
            }
    
            #endregion
    
            #region IDataErrorInfo for View
    
            public string this[string dataFieldName]
            {
                get
                {
                    //CommandManager.InvalidateRequerySuggested(); does not work
                    var result = Validate(dataFieldName);
                    return result;
                }
            }
    
            public string Error
            {
                get
                {
                    // return this[string.Empty or Null] does not work
                    return null;
                }
            }
    
            #endregion
    
        public class LegGridVMData : ViewModelItemBase, IDXDataErrorInfo
        {
            #region Fields
    
            private string _p1;
            public string VMP1
            {
                get { return _p1;}
                set
                {
                    _p1= value;
                    NotifyPropertyChanged(() => WMP1);
                }
            }
    
      
    
            #endregion
    
            #region IDXDataErrorInfo for View
    
    
            public void GetError(ErrorInfo info)
            {
              // chose not to cluster error message to row level
            }
    
            public void GetPropertyError(string propertyName, ErrorInfo info)
            {
                info.ErrorType = ErrorType.Information;
                info.ErrorText= Validdate(propertyName);
            }
    
            #endregion
    
            #region Validation for VM
    
            public string Validdate(string propertyName)
            {
                switch (propertyName)
                {
                    case "VMP1":
                        if (string.IsNullOrEmpty(VMP1))
                        {
                            return "Please select a VMp1";
                        }
                        break;
                    ...
               
    
                
                }
                return null;
            }
    
    
    
            #endregion
    
    
    
            private bool CanExecuteOk()
            {
                return ViewModel.IsValid;
            }
    
            private void TriggerViewModelChirldsValidation()
            {
                ViewModel.Chirlds = ViewModel.Chirlds;  // Hack: assign itself to trigger Validation, w/o makeing NotifyPropertyChanged public.
            }
    
    
           void ListenToPropertyChangedEvent()
            {
                if (ViewModel == null || ViewModel.Chirlds == null) return;
                foreach (var l in ViewModel.Chirlds)
                    l.PropertyChanged += OnPropertyChanged;
    
                ViewModel.PropertyChanged += OnPropertyChanged;
            }
    
    
            void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
            {
                if (e.PropertyName == "IsValid")  // IsValid changes => reevaluate CanExecute.
                {
                    var cmd = ViewModel.OkCommand as DeChirldateCommand;
                    if (cmd != null) cmd.RaiseCanExecuteChanged();
                }
                else  // otherwise, just do re-evaludation of IsValid
                {
                    ViewModel.Validate();
                }
    
                if (e.PropertyName == "IsRef")
                {
                    TriggerViewModelChildrenValidation();  // Trigger one and only one Ref validation on Ref checkbox
                }
    
            }
    

    Friday, October 31, 2014

    Comparing code using WPF Perforate and Visual Profiler

    
    For INPC code vs non standard code, there are some steps we can follow:
            private double? _q;
            public double? Qty
            {
              ... NotifyPropertyChanged(this,"Qty");
            }
    
            private double? _q;
            public double? Qty
            {
                get { return GetQty(0); }
                set { _bidQtys[0] = value; }  // by adding NotifyPropertyChanged(this,"Qty") here speed will pick  up to standard INPC
    
    (1) generate stressfull/human data 1ms, 10ms 250ms and bind to WPF Xaml UI
                d = Observable.Interval(TimeSpan.FromMilliseconds(1)).Delay(TimeSpan.FromSeconds(20)).Subscribe((ms) =>
                {
                    Random r = new Random();
                    for (int i = 0; i < FakeData.Count; i++)
                    {
                        FakeData[i].Qty = -1000 * r.NextDouble();
    
    (2) Perforator:FRPS/DRAR higher=> data updates faster (Key Observation: INPC has 9x FRPS than non-standard that use intermediate storage
    (3) VisualProfiler CPU %
     DispatcherInvoke -- Dispatcher Operation,  Increasing to high=> buggy code, e.g too many timer pushing UI
    
     Rendering Thread --- Unmanaged render pass (Brushed, tessalation, call DirectX), find only the visual element and draws 
    
    the whole window at a 60 FPS as default, popularly called as Composition Thread , Graphics acceleration uses Channel 
    
    Protocol to communicate with the other thread. High and increasing % => need to Profile to feed XPerf, GPUViwer, WPA, 
    
    etc in Windows Performance ToolKit.
    
     Layout ---measure/arrange passes higher => variable/Compute control size, fast changing text, bad GPU/Box.
    
    (4) 1ms -- most stressful  10ms -- Physical limit 16ms per frame =60 FRPS, 250 Human eyeball, Win8 App Fast= 100-200ms
    

    Sunday, October 19, 2014

    Rx ObserveOn SubscribeOn

    In WPF Window update UI code look like the follwoing:
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                Observable.Interval(TimeSpan.FromSeconds(1)).ObserveOn(Dispatcher).Subscribe((i) => this.Title = i.ToString());
            }
        }
    or
    
     Observable.Interval(TimeSpan.FromSeconds(1)).ObserveOn(this).Subscribe((i) => this.Title = i.ToString());
    
    ObserveOn = Notify Observer on a Dispatcher
    SubscribeOn = Subscribe/unsubscribe Observers on a scheduler, where background/task pool will run.
    

    Friday, October 10, 2014

    Useful Tools, scripts and Concept

    
    Power Shell set path
    ====================
    (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
    
    $oldPath=(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
    
    $newPath=$oldPath+’;C:\tools\snoop\’
    
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH –Value $newPath
    
    Power Shell:
    ============
    get-childitem | select-string "double"  ( find string)
    get-ChildItem -Path c:\log |select-string "error"
    
    add user to admin  net localgroup Administrators /Add Domain\UserId
    
    Color Hex converter
    ===================
    http://www.colorschemer.com/online.html
    
    Performance Tools and Concept
    ==============================
    
    Vsync --- GPU sync up buffers and refresh rate so no Tearning (frame override previous one). If GPU does not finsh render before one VSync,
     then could CPU taking too long.
    XPerf/WPA --ETW (CLR GC/ThreadPool/JIT events, Context Switching, CPU, Page Fault, Disk IO, reg access) best OS logging. some managed code
    
    PerfView --- Managed code, Stacks (CPU,Disk IO, GC Head Alloc,Image Load, Managed Load), Stats(GC, JIT,Event)
    
    Some details on PerfView:g 
    =========================
    (1) Memory -> Task Snapshot of Heap -> filter to your process -> Force GC-> dump your GC heap => can compare be
    fore after closing of some part of UI to see if Memory get reclaimed.
    
    (2)CPU Stack high CPU % path drill down can identify hot code.
    
    (3) Run Command " your.exe" will still collect all ETW data so you have to drill down to "your.exe". But this will bracket the time you are interested in.  The other is "Collect"
    
    (4) PerfView is for  managed code. So before any analysis, use VMMap to check workingset break down: Heap vs. Managed Heap size. Also, Task manager private Memory column can tell if Memory stay high and increasing even after some view are closed or running for a long time.
    
    (5) Diff requires open two stack viewer of dump to diff. If Comparison to baseline show positive MB=> memory increase or baseline reclaimed GC Heap after GC dump and your app GC Dump.
    (6) Click on a row in diff stack => trace back to root where you can start to analyze source code for who is holding heap memory.
    (7) Wall Clock Analysis: Collect ->check Thread Time-> get 3 Thread time view stack in collected data.
    (8) CPU_TIME, BLOCK_TIME= waiting for eg disk access come back, PAGE_FAULT= Virtual Ram. Ctx Menu Include Item/Back button can focus/exit on CPU_TIME.
    (9) Zoom in = Select two cell -> set time range 
    (10) Thread Time (With Task)--- charge Child task related time to Parent Task so time will be for the child  real work not in the task. Next use Include item can zoom in to the code in the thread that use Wall Clock time.
    

    Tuesday, September 23, 2014

    Using DevExpress Layout Manager access a View from Shell

    When View (UserControl) cannot be access from Presenter and burried inside inside a shared DLL, you may use Shell Window
     to walk up/down tree. But some docking situation requires using DockLayoutManager to track down. 
    
    
                var shellWindow = _mySvc.GetApplicationShell() as XpfRibbonShellView;
                if (shellWindow == null) return;
    
                shellWindow.Dispatcher.Invoke(new Action(() =>
                {
                    try
                    {
                        // when TheView is docked
                        var wrkSpace = VisualTreeHelpers.FindChild<ContentControl>(shellWindow, "wrkSpace");
                        var gContent = VisualTreeHelpers.FindChild<GroupPaneContentPresenter>(wrkSpace, "PART_Content");
                        var lpItemsCtl = VisualTreeHelpers.FindChild<LayoutItemsControl>(gContent);
    
                        foreach (var i in lpItemsCtl.Items)
                        {
                            // TheView docked top layer
                            var lp = i as LayoutPanel;
                            if (lp != null && lp.Content is TheView)
                                lp.ShowCaption = true;
    
    
                            // TheView Tabbed inside another docked
                            var lg = i as LayoutGroup;
                            if (lg == null) continue;
                            foreach (var i2 in lg.Items)
                            {
                                var tg = i2 as TabbedGroup;
                                if (tg != null)
                                {
                                    var layoutItems = tg.GetItems();
                                    foreach (var lp2 in layoutItems.Cast<LayoutPanel>().Where(lp2 => lp2.Content is TheView))
                                    {
                                        lp2.ShowCaption = true;
                                    }
                                }
                                // TheView could end up here if close and then added back whiel in Tab mode
                                var lp3 = i2 as LayoutPanel;
                                if (lp3 != null && lp3.Content is TheView)
                                    lp3.ShowCaption = true;
                            }
                        }
    
                        // When TheView is floating
                        foreach (var lp in shellWindow.DockLayoutManager.FloatGroups.SelectMany(fg => fg.Items.OfType<LayoutPanel>().Where(lp => lp.Content is TheView)))
                        {
                            lp.ShowCaption = true;
                        }
    
                        // All auto hide layout panel need to be handled here , not just TheView.
                        foreach (var lp in shellWindow.DockLayoutManager.AutoHideGroups.SelectMany(ahGroup => ahGroup.Items).OfType<LayoutPanel>())
                        {
                            lp.ShowCaption = true;
                        }
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex);
                    }
                }));
    

    Sunday, September 21, 2014

    Low Latency Programing

    
    Looks like their thinking are influenced by Peter Lowery' s Talk on Friday and possibly by
     Martin Fowler and Martin Thompson's writing about Low Latency.
    
    I think there are two things highly relevant to Insight-Desktop (Carol, Hai, Daniel, Alec also in Peter's talk so please comment)
    
    (1) Journaling, aka EventSourcing
       The idea is to log every input event and replay them to help debug PROD issue in DEV. Obviously, we need a low latency logger
    
    (2) Profile Market watch.
       I think Market Data come in here. We should profile for GC pause, Lock contentioin, Caching.
       This help us to understand MVVM + Presenter pattern better in term of low latency,
    
    Here are key points from their talk/writing
    
    Setup correct performance test --- Theory are most likely wrong.
    GC-Free  ---The biggest Performance cost is GC Pause
    Lock-Free  ---- Lock cause Context switching, clear cache line
    Cache Friendly --- L3 Cache is shared memory cross cores.
    EventSourcing --- Replay input event to debug PROD in DEV, instead of analysing Log files
    
    Actionable Items:
    
    (1) Performance Benchmark Test App: 
        A WPF Unit testing simulator can be build for Logging, Journaling, Rx vs. .Net event, Market data <100 micro-second.
    
    (2) Logging Improvement:
        a separate email thread already starting writing a logging using RingBuffer.
    
        
    
    
    
    Shared Memory (L3 cache), Cache Friendly Collectioin
    Thread Affinity and Isolation
    Queue (LinkedList, Array) Ring Buffer, In Memory
    
    Concurrency
    Single Threaded, Fx 4.5 Async-Await
    Journaler, Sequential Disk
    
    Array is Cache Friendly.
    
    64-bit Cache key, Concurrent Map/Segments, 1000 Segments. Producer never block to wait consumer
    
     Loop unrolling,Lock-coarsing, Inlining
    
    Queue has fundamental Issues, Ring Buffer is better but on Dsktop cannot have 10M
    
    Network: 10mcs local hop, 10GigE, FPGA market Data
    
    
    http://mechanical-sympathy.blogspot.hk/
    
    http://martinfowler.com/articles/lmax.html - even martin fowler has done a review of it
    
    http://lmax-exchange.github.io/disruptor/ - all the source code is on github
    
    http://www.infoq.com/presentations/LMAX - presentation on the architecture
    
    
    

    Tuesday, September 16, 2014

    How to visualize UI hanging using Concurrency Visualizer in VS 2013

    Fx 4.5 Aysnc-Wait allow UI Processing 80%+ of time, while Fx 4.0 Blocking Collection only allow 20%-
    
    
    
    Ring Buffer looks better in UI Processing more like 40%

    Sunday, September 14, 2014

    Classical Asyn Pattern and "AsyncRollingFileAppender" using BlockingCollection in Log4Net

    Action a = ()=>{ do some work};
                    a.BeginInvoke(CB, a);
            void CB(IAsyncResult ar)
            {
                Action a = ar.AsyncState as Action;
                a.EndInvoke(ar);
            }
    
    
    (1) It seems UI Async cannot be implemented in Fx 4.0.
        We have to wait for Fx 4.5 async-await to have non-blocking UI
    (2) AsyncRollingFile is  "async-like", slightly block UI. In my test it
        blocking UI for 9 seconds, then writing file take 40 seconds to complete.
        It is definetly faster than classic Log4net RollingFile which block UI by the entire 40 secs.
    (3) Log4Net achieved Async by using Task offloading logging from a 
        queue-like buffer.I also tried TaskCompletionSource and it has similar "short-blocking" async behavior.
    (4) All these async-alike can lose 20 seconds of data during delayed write to files since app can crash. 
        That is  when we really need to log why the app crashed.
    (5) Fx 4.0 already has a solution to deal with Buffer overflow in Log4NetAsync --- instead of throw away
        logging, we can block logging. So we slow down but do no lose data.
        Specifically, I think we can implement IProducerConsumer using RingBuffer (so 2x faster writing files)
        and feed it to BlockingCollection with Capacity 1000.
        I tried BlockingCollection, capacity 10 or 1000, default ConcurrentQueue, end up Blocking UI for 20 secs and
        70 sec write to files. so much slower.
    
                Stopwatch sw = new Stopwatch();
                sw.Start();
                for (int i = 0; i < Int32.MaxValue / 1000; i++)
                   // your Log.Info
                sw.Stop();
                MessageBox.Show(sw.ElapsedMilliseconds.ToString());
    
    
    namespace Log4Net.Async
    {
        public class AsyncRollingFileAppender : RollingFileAppender
        {
            BlockingCollection<LoggingEvent> pendingAppends = new BlockingCollection<LoggingEvent>(10);
    
            Task t ;
            public override void ActivateOptions()
            {
                base.ActivateOptions();
                 t = new Task(AppendLoggingEvents,TaskCreationOptions.PreferFairness);
                 t.Start();
            }
    
            protected override void Append(LoggingEvent[] loggingEvents)
            {
                Array.ForEach(loggingEvents, Append);
            }
           
            protected override void Append(LoggingEvent loggingEvent)
            {
    
                Task.Factory.StartNew(() =>
                {
                    
                    if (FilterEvent(loggingEvent))
                    {
                        pendingAppends.Add(loggingEvent);
                    }
                });
            }
    
            private void AppendLoggingEvents()
            {
                LoggingEvent loggingEventToAppend;
                while (true)
                {
    
                    while (!pendingAppends.TryTake(out loggingEventToAppend))
                    {
    
                    }
                    if (loggingEventToAppend == null)
                    {
                        continue;
                    }
    
                    try
                    {
                        base.Append(loggingEventToAppend);
                    }
                    catch
                    {
                    }
                }
    
                while (pendingAppends.TryTake(out loggingEventToAppend))
                {
                    try
                    {
                       
                        base.Append(loggingEventToAppend);
                    }
                    catch
                    {
                    }
                }
            }
        }
    }
    
    

    Monday, September 1, 2014

    MEF Injects UserControls, Property and Method as Action, Func

    (1) [ImportMany] handles 0 matching [Export] without blow up
    (2) container.GetExportedValueOrDefault trigger IoC DI for Extensions Class
    (3) IPartImportsSatisfiedNotification delay  construction of property after Ctor.
    (4) Obs showed that realtime changes are injected as well.
    
        public partial class App : Application
        {
    
            protected override void OnStartup(StartupEventArgs e)
            {
                AggregateCatalog aCat = new AggregateCatalog(
                    new AssemblyCatalog(Assembly.GetExecutingAssembly()),
                    new DirectoryCatalog(@".\Execution")
                    );
                var container = new CompositionContainer(aCat);
                Window w = container.GetExportedValueOrDefault();
                w.Show();
            } 
        }
    
        [Export(typeof(Window))]
        public partial class MainWindow : Window, IPartImportsSatisfiedNotification
        {
    
            [ImportMany("ListUC",typeof(FrameworkElement))]
            IEnumerable controls { get; set; }
    
            [ImportMany("WinStyle", typeof(WindowStyle))]
            WindowStyle[] WinStyles { get; set; }
    
            [ImportMany("SetWinStyle", typeof(Action))]
            Action[] WinStyleActions { get; set; }
          
            public void OnImportsSatisfied()
            {
                List l = new List(controls);
                list.ItemsSource = l; // Xaml code inject a list of UC Controls 
                if (WinStyles.Length > 0)
                    WindowStyle = WinStyles[0];
                if(WinStyleActions.Length>0)
                WinStyleActions[0](this);
            }
        }
    
    
        public class MyExtensions
        {
           [Export("WinStyle", typeof(WindowStyle))]
            public WindowStyle WindS
            {
    
                get { return WindowStyle.None; }
            }
         
            [Export("SetWinStyle")]
           public void SetWinStyle(Window w)
           {
               MessageBox.Show(this.ToString());
                Observable.Interval(TimeSpan.FromSeconds(3)).SubscribeOn(SynchronizationContext.Current).Subscribe((s) =>
                 {
                     w.Dispatcher.Invoke(new Action(() =>
                     {
                         w.WindowStyle = w.WindowStyle == WindowStyle.ThreeDBorderWindow ? WindowStyle.None : WindowStyle.ThreeDBorderWindow;
                     }));
                 });
               
           }
        }
    
    
      [Export("ListUC",typeof(FrameworkElement))]
        public partial class UserControl1 : UserControl
        {
            public UserControl1()
            {
                InitializeComponent();
            }
        }
    
    

    Thursday, August 28, 2014

    Set property value without reference types

    Including Reference could mess up code (e.g circulare refernce or DI failure). So use reflection while walk up down logical tree will fix that. In fact, runtime type resolution in dynamic language does just that.
            void SetPropertyOfAncestor(FrameworkElement framewkElement, string AncestorTypeName,string propName, object propValue)
            {
                FrameworkElement current = VisualTreeHelper.GetParent(framewkElement) as FrameworkElement;
                while (current != null)
                {
                    Type t = current.GetType();
                    if (t.Name == AncestorTypeName)
                    {
                        PropertyInfo pi = t.GetProperty(propName);
                        if (pi != null)
                        {
                            pi.SetValue(current, propValue, null);
                            return;
                        }
                        else
                        {
                            current = VisualTreeHelper.GetParent(current) as FrameworkElement;
                        }
                    }
                    else
                    {
                        current = VisualTreeHelper.GetParent(current) as FrameworkElement;
                    }
                }
            }
    

    Tuesday, August 19, 2014

    WPF UI Automation C# and IronPython Code

    Tools: add referecne to UIAutmationClient and UIAutomationTypes. Inspect.exe under local Windows SDK 
    directory, used for find AutomationId, name of logical tree, similar to Scoop.
    
                Process p = Process.Start(@"..\..\..\TryoutUITesting\bin\Debug\TryoutUITesting.exe");
                AutomationElement desktop = AutomationElement.RootElement;
                AutomationElement mainWin =null;
                while( (mainWin= desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "MainWindow")))==null) {}
              AutomationElement button=  mainWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "btn"));
              InvokePattern buttonClick = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
              buttonClick.Invoke();
    
              AutomationElement textbox = mainWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "tbx"));
              TextPattern textboxText= textbox.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
              string result = textboxText.DocumentRange.GetText(-1);
              Debug.Assert(result == "Foo");
    
    
    from System.Diagnostics import Process
    from System.Diagnostics import Debug
    
    import clr
    clr.AddReference("UIAutomationClient")
    clr.AddReference("UIAutomationTypes")
    from System.Windows.Automation import *
    from System.Windows.Automation import PropertyCondition
    
    
    def main():
        p=Process.Start("C:\\working\\TryoutWPFTesting\\TryoutWPFTesting\\bin\\Debug\\TryoutWPFTesting.exe")
        desktop=AutomationElement.RootElement
    
        mainWin =None
        while (mainWin==None): 
            mainWin= desktop.FindFirst(TreeScope.Children, PropertyCondition(AutomationElement.NameProperty, "MainWindow"))
    
        button=  mainWin.FindFirst(TreeScope.Children, PropertyCondition(AutomationElement.AutomationIdProperty, "btn"))
        buttonClick = button.GetCurrentPattern(InvokePattern.Pattern)
        buttonClick.Invoke()
     
        textbox = mainWin.FindFirst(TreeScope.Children, PropertyCondition(AutomationElement.AutomationIdProperty, "tbx"))
        textboxText= textbox.GetCurrentPattern(TextPattern.Pattern)
        result = textboxText.DocumentRange.GetText(-1);
        Debug.Assert(result == "Foo");
        p.WaitForExit()
    
    if __name__=="__main__":
        main()
    

    Tuesday, August 12, 2014

    Git Branching Strategy

    Pull = update your feature branch or local copy before commit/merge.
    Fetch = update local master, not your branch
    Fast Forward != merge
    Merge = heavies and post feature development
    
    Rebase = Complicated, carry history, Pull down code relative to upstream/mster.
    
    
    Three rebase Scenarios
    
    

    Monday, August 11, 2014

    Custom Region Adapter

    IRegionManager can register view with Region but by default only works for Content Control (single item), ItemsControl (2+ Items)
       <ContentControl Grid.Row="1"  cal:RegionManager.RegionName="{x:Static def:RegionNames.PricingGridRegion}" />
        regMgr.RegisterViewWithRegion("PricingGridRegion", typeof(DurationTraderView));
    
            <!--<ItemsControl cal:RegionManager.RegionName="{x:Static def:RegionNames.PricingGridRegion}"/>-->
    
            <StackPanel cal:RegionManager.RegionName="{x:Static def:RegionNames.PricingGridRegion}" Orientation="Horizontal" FlowDirection="RightToLeft" />
    
    Custom Region Adapter is needed to register into Stack Panel:
    
        public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
        {
            public StackPanelRegionAdapter(RegionBehaviorFactory factory) : base(factory) { }
    
    
            protected override void Adapt(IRegion region, StackPanel regionTarget)
            {
                region.Views.CollectionChanged+=(s,ea)=>
                    {
                        if(ea.Action== NotifyCollectionChangedAction.Add)
                        {
                            foreach(FrameworkElement fe in ea.NewItems)
                            {
                             regionTarget.Children.Add(fe);
                            }
                        }
                    };
            }
    
            protected override IRegion CreateRegion()
            {
                return new AllActiveRegion();
              //  return new SingleActiveRegion(); // if onely one item
            }
    
        }
    
        public class Module : IModule
        {
            public void Initialize()
            {
                IRegion reg = _regMgr.Regions[RegionNames.PricingGridRegion];
                reg.Add(_container.Resolve<SampleView>());
                reg.Add(_container.Resolve<SampleView>());
                reg.Add(_container.Resolve<SampleView>());
                reg.Add(_container.Resolve<SampleView>());
                reg.Add(_container.Resolve<SampleView>());
            }
    
    
    

    Saturday, August 9, 2014

    Basis Spread and Butterfly Spread Trading

    Simplest Price based spread trading
    

    Friday, August 8, 2014

    Covariant and Contravariant

    Note that these constraints can be overridden by code, extension method to convert anything to anything
    
        class Program
        {
            static void Main(string[] args)
            {
                IW<String> iwStr = new W<string>("Test");
                IW<object> iwObj =  iwStr.ToObject2();
            } 
        }
    
        public interface IW<T>
        {
            T W { get;  }
        }
    
        public class W<T> : IW<T>
        {
            T _w;
            public W(T w)
            {
                _w = w;
            }
            T IW<T>.W
            {
                get { return _w; }
            }
        }
    
        public static  class Ext
        {
            public static IW<object> ToObject2(this IW<string> iw)
            {
                return new W<object>(iw.W);
            }
        }
    

    Thursday, August 7, 2014

    Notes on Expression Blend

    1. Gradient can used on Background and Opacity Mask. the latter could be on an Image
    
    2. Control States are model by Visual State Group (Common, Focused) and a grid can have Opacity set for two group if not conflict
        These states are visible only Edit Template --> Edit Copy for a control.
    
    3. Two workspace under windows: Design and Animation. The 1st relates to animation by Assets-> Control  StoryBoard action and 
    set event trigger  and StoryBoard1.
    
    4. Animation workSpace can utilize Transform Property and specifically Layout Transform to do Rotation. It may need to first turn off 
    recording for StoryBoard to set key frame at 0 sec, then recording on to drag to sec to rotate 360 and restore size back.
    
    5. Any group of Path, Drawing, Image, Controls can be Object/Timeline -->select multiple--> right click->Control->make User Control.
    Its code behind can define a public prop showing up in Properties Grid Misc when it is hosted in a MainWindow.xaml.
    
    6. Shape Set Operation and arbitrary path generation: any two shape can object->Combine -->(Unit, Substract, Intersect), including 
    TextBlock where text can be substracted.  Also can convert Shape to path by Object->Path-->Convert to path. 
    
    7. Carry User Control around: User Control build in Control Library Project can be used in WPF project seen under Assets Tab. 
    Need to add project references. This also works even for any project type but have to manually add/remove when UC changes. Also add existing
     item as UC but that is just a copy of Xaml and cs and new changes will not automatically moved.
    
    8. Easing Function: must select a Key Frame for property visible, in Animation Workspace. KeySpline =Simple cubic,Hold-in=no interpolation,
     direct to the end. 
    
    9. Layout Controls: Grid's ScrollbarVisibility Property checkbox are attached property ScrollViewer.* and
     does not work well. So directly set it on ScrollViewer if you can; DockPanel LastChildFill also attached
     property and override the last child dock.
    
    10. Layout Controls has Canvas and Grid, Grid has two mode: Grid Model and Canvas mode. the latter mode is not Canvas but behave 
    like one --- child control are absolutely positioned not responding to Grid resizing.
    
    11. Layout controls Border is very different: it has Border Brush, Back Ground, Corner Radius. But it can only hold one child.
     To host more children need to Object->Group into --> Grid to add grid and drag on more child.
    

    Monday, July 28, 2014

    VS.Net Environment Configuration "Add-in" -- now called VS Package

    (1) Install VS 2010 SP1 SDK
    (2) Tool -- Extension Manager, search VSPackage, install VSPackage Template and VSPackage Builder template
    (3) New Project, the Builder, Drag on "Add Toolbar" from toolbox, add two Combo, one button. Connect them to Group1.
    
    Now all will show up in Toolbar.
    
    Code to get Configuration Data from Server Http Endpoint--- must write in a seperate class file or Builder will overwrite it.
    
        class Configurator
        {
            public static string StartProjectName { get; private set; }
            public static void SetStartArguments(EnvDTE.DTE dte,string currEnvCombo, string currVerCombo)
            {
                foreach (Project p in dte.Solution.Projects)
                {
                    if (p.Name == StartProjectName)
                    p.ConfigurationManager.ActiveConfiguration.Properties.Item("StartArguments").Value = "env="+currEnvCombo+"\r\nver="+currVerCombo+"\r\nwebdata="+data;
                }
            }
    
            static string data = "";
            public static void ReadConfigurationFromServer(ref string[] envArray, ref string[] verArray)
            {
                // Get Configuration from Server for all (env ver) and set two combo, start project etc.
                WebClient wc = new WebClient();
                data = wc.DownloadString("http://www.cnn.com").Substring(300, 10);
                StartProjectName = "WpfApplication1";
                envArray=new string[]{"UAT","LIVE","Local"};
                verArray=new string[]{"Trading (London)","Trading (NYC)","Sales"};
            }
        }
    
            public VSPackage1PackageBase()
            {
                Configurator.ReadConfigurationFromServer(ref envComboChoices, ref verComboChoices);
            }
    
            protected virtual void envComboExecuteHandler(object sender, EventArgs e)
            { ...
            Configurator.SetStartArguments(GetService(typeof(DTE)) as DTE, currentenvComboChoice, currentverComboChoice);
    
    Deployment: VSPackage project auto generate .vsix file for installation. But Do check vsixmanifest file "Select Editions" to include all VS.net 2010 editions
    

    Thursday, July 24, 2014

    Practical MVVM/RX WPF App

    
    Building MVVM/Rx WPF need to glue together multiple interface and correctly hand off to Dispatcher:
    
    (1) (engineering) Need to use nuget.config align with .sln so package managed at solution level 
              <add key="repositorypath" value="Packages" />
    
    (2) (design pattern) View - ViewModel --VMController--Adapter -- Transport
    
    (3) (engineering) Fluent API can easily glue DataContext to VM, VMController point to VM
    
        public class FluentFactory
        {
            public FluentFactory ViewModelController(Func<IViewModelController> viewModelControllerFactory)
            {
                var f = viewModelControllerFactory.Invoke();
                f.ViewModel = _viewModel;
                return this;
            }
    
            INotifyPropertyChanged _viewModel=null;
            public FluentFactory ViewModel(Func<INotifyPropertyChanged> viewModelFactory)
            {
                _viewModel = viewModelFactory.Invoke();
                return this;
            }
    
            public void View(Func<FrameworkElement> viewFactory)
            {
                FrameworkElement fe = viewFactory.Invoke();
                fe.DataContext = _viewModel;
            }
        }
    
    (4) (MVVM) Module can resolve instance to inject into DockingViewManager
        public class TradingModule : IModule
        {
            IUnityContainer _container;
            public TradingModule(IUnityContainer container)
            {
                _container = container;
            }
            public void Initialize()
            {
                _container.RegisterInstance<ITransport>(new TradingTransport());
                _container.RegisterInstance<IAdapter>(new TradingAdapter());
                _container.RegisterInstance<IScheduler>(new NewThreadScheduler());
                _container.RegisterInstance<LocalScheduler>(DispatcherScheduler.Current);
            }
        }
    
    (5) (Rx) DockingViewManager will Create VMController when Button Click ask for well known view and then start Observable sequence
    
        public class DockingViewManager : IDockingViewManager
        {
            public DockingViewManager(ITransport transport, IAdapter adapter, IScheduler scheduler, LocalScheduler dispatcher)
    
            public UserControl GetDockingView(WellknowViewName viewName)
            {
                FluentFactory f = new FluentFactory();
                if (viewName == WellknowViewName.DurationTraderView)
                {
                    DurationTraderView durView = new DurationTraderView();
    
                    f.ViewModel(() => new DurationTraderViewModel())
                    .ViewModelController(() => CreateDurationTraderViewModelController())
                    .View(() => durView);
                    return durView;
                }
    
                if (viewName == WellknowViewName._5_10Yr)
                {
                    _5_10YRView view = new _5_10YRView();
    
                    f.ViewModel(() => new _5_10YRViewModel())
                    .ViewModelController(() => Create_5_10YRViewModelController())
                    .View(() => view);
                    return view;
                }
                return new UserControl();
            }
    
            public DurationTraderViewModelController CreateDurationTraderViewModelController()
            {
                return new DurationTraderViewModelController(_transport,_adapter,_scheduler,_dispatcher);
            }
        }
    
    
        public class DurationTraderViewModelController : IViewModelController
        {
            public INotifyPropertyChanged ViewModel { get; set; }
    
            public DurationTraderViewModelController(ITransport transport, IAdapter adapter, IScheduler scheduler, LocalScheduler dispatcher)
            {
                transport.GetTradingObservables()
                    .SubscribeOn(scheduler)
                    .ObserveOn(dispatcher)
                    .Subscribe(fSet => adapter.updater(fSet, ViewModel));
            }
        }
    
        public class TradingTransport : ITransport
        {
            public IObservable<IFieldDataSet> GetTradingObservables()
            {
                return Observable.Create<IFieldDataSet>((obsr) =>
                {
                    return Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1)).Select(i => new FieldDataSet()).Subscribe(obsr);
                });
            }
        }
    
    Side Note--- OnPropertyChange("Cusip") is error prone with Hard-coded string. Better utilize Expression tree in C# 4.0
         
            SetProperty(ref _cusip, value,()=>Cusip);
    
            public void SetProperty<T>(ref T field, T value, Expression<Func<T>> exp)
            {
                if (EqualityComparer<T>.Default.Equals(field, value)) return;
                field = value;
                if (PropertyChanged != null)
                {
                    MemberExpression me = exp.Body as MemberExpression;
                    if (me != null && me.Member != null)
                        PropertyChanged(this, new PropertyChangedEventArgs(me.Member.Name));
                }
            }
    
    Side Note --- Load Module by Config
      <modules>
        <module assemblyFile="Modules.dll" 
                moduleType="Modules.TradingModule, Modules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                moduleName="TradingModule" startupLoaded="true" />
      </modules>
    
        public class DemoUnityBootstrapper : UnityBootstrapper
        {
            protected override IModuleCatalog CreateModuleCatalog()
            {
                return new ConfigurationModuleCatalog();
            }
        }
    
    

    Sunday, July 6, 2014

    Producer Consumer Pattern with HandOff point

    // Both Data Queue and Queue under SynchronizationContext allow handoff of data
    // Data Consumer can be parallel Enumerable or Subscribe to Observables
    // UI can only singled threaded Async or sync
    
            void BlockingCollectionAsQueue()
            {
                BlockingCollection<string> ServerData = new BlockingCollection<string>(10000);
                ServerData.Add("Data");
                ServerData.CompleteAdding();
                string data1;
                ServerData.TryTake(out data1, TimeSpan.FromMilliseconds(2));
                IEnumerable<string> data = ServerData.GetConsumingEnumerable();
                foreach (var v in data.AsParallel().AsOrdered().Select(l => Regex.Replace(l, @"\s+", ""))) ;
            }
    
            void UIMarshalling()
            {
                ThreadPool.QueueUserWorkItem((s) =>
                {
                    //do some server side work
                    // UIControl.Invoke();
                    //Dispatcher.Invoke();
                    SendOrPostCallback spcb = new SendOrPostCallback((obj) => { });
                    // SynchronizationContext =WPF.Dispatcher or WF.Control.Invoke
                    SynchronizationContext.Current.Send((state) =>
                    {
                        //UI.Property="";
                    }, "");
                });
            }
    
    http://www.martinpersson.org/wordpress/2012/12/application-launcher/

    TPL Fork Join code Pattern

    // Count down until all 4 are signaled
         CountdownEvent ce = new CountdownEvent(4);
                ce.Signal();
                ce.Wait();
    
    // count up by add one for each work
         ce = new CountdownEvent(1);
         ce.AddCount(1);
         ce.Signal();
         ce.Wait();
    
    // Inlining -- Recursive Decomposition
     // walk by directly parallel
            void Walk2<T>(Tree<T> root, Action<T> action)
            {
                if (root == null) return;
                Parallel.Invoke(
                    ()=> action(root.Data),
                    () => Walk2(root.Left, action),
                    () => Walk2(root.Right, action));
            }
    
    //Continuation Chaining
    // Parallel <> Sum of Tasks, Unwrap() map Task<Task> to Task for Completion.
                if (root == null) return _CompletedTask;
                Task<Task> t2 = Task.Factory.StartNew(() => Walk(root.Left, action));
                Task<Task> t3 = Task.Factory.StartNew(() => Walk(root.Right, action));
                return Task.Factory.ContinueWhenAll(new Task[] { t1, t2.Unwrap(), t3.Unwrap() },
                 task => Task.WaitAll(task));
    public static Task _CompletedTask = ((Func<Task>)(() =>
            {
                TaskCompletionSource<object> ts = new TaskCompletionSource<object>();
                ts.SetResult(null);
                return ts.Task;
            }))();
    
    //Parallel with options:
    // option can cacell, set schedule, MaxDegree.
    // Parallel.For can be stoped by loop.Stop() inside For
    Parallel.Invoke(opts, () => { }, () => { }, () => { });
                CancellationTokenSource ts = new CancellationTokenSource();
                
                ParallelOptions opts = new ParallelOptions()
                {
                    MaxDegreeOfParallelism = 2,
                    TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(),
                    CancellationToken = ts.Token
                };
    
     ParallelLoopResult res = Parallel.For(0, 10000, () => 1, (j, loop, sub) =>
                {
                    if (loop.ShouldExitCurrentIteration) return 0;
                    loop.Stop();
    

    Testing Observables using NUnit/Moq in MVVM

    Mock->setup a function must run for each parameter change.
    Obs.Create take in IObser and return IDispoable. So next a Subject to call OnNext.
    Note that Subject.sub(Obr) will allow OnNext to stream out Obs.
    Finally, testSchedule must advance to see data coming out.
    
    Mock _mockT= Mock;
    _VMController = new(_mockT.Object, ...);
    [Test] public void IdChanged() {
       Id = new Hashset(){guid};
       _mockT.Setup(p=>ObserveData(Id)
       .Return(GenerateObs(id:Id, data: 100.01));
       Assert.AreEqual(_VMController.ViewModel.DataCollecton.Count,1);
    }
    IObs<PT> GenerateObs(string id="", double? data=null,DateTime logicalDate=null) {
    Data data = new (...);
    return Observable.Create(obsr=>{   // Func<IObserver,IDispoable>
    var s = new Subject<Data>();
       s.subscribe(obsr);
       onNext<Data>(s,data);
    return s;
    });
    }
    void onNext<T> (IObserver obr, T data)
    {
      obr.OnNext(data);
      _testSchedule.AdvancedBy(250ms);
    }
    

    Sunday, June 29, 2014

    Use TPL/ TaskCompletionSouce to Implement DownloadAsync

    Using Task create non-blocking, TaskCompletionSource SetResult helps send result accross
            static void Main(string[] args)
            {
                Task<string> t = DownloadAsync();
                Console.WriteLine("Do some other work while wating for Async Donwload");
                Thread.Sleep(3000);
                Console.WriteLine("other work done");
                t.ContinueWith((t1) => { Console.WriteLine(t1.Result); });
                // Task.WaitAny(new[] { t }); Wait =Readline to keep program running
               // Console.WriteLine(t.Result);
                Console.ReadLine();
            }
    
            static Task DownloadAsync()
            {
                TaskCompletionSource<string> ts = new TaskCompletionSource<string>();
                string i="";
                Task.Factory.StartNew(()=> { i = DownloadSync(); }).ContinueWith((t)=>
                { ts.SetResult(i); });
                return ts.Task;
    
            }
            
            static string DownloadSync()
            {
                Thread.Sleep(5000);
                return "Data";
            }
    
    

    Saturday, June 28, 2014

    Convert Property Change to Observable

    INPC enable binding V <-> VM and need ICommand to execute request to Server side. It is interesting to see if Observables in Rx running on
    a TaskPoolScheduler can do the same as Delagete or Relay Command. Both FromEventPattern and CLR event should work
    
        public class ViewModel : INotifyPropertyChanged
        {
            public string Cusip { get; set; }
            public double Ask { get;set; }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            public IObservable<Tuple<T, string>> OnSubmitChanges<T>(Expression<Func<ViewModel, T>> exp)
            {
                MemberExpression me = exp.Body as MemberExpression;
                string n = me.Member.Name;
                Func<ViewModel, T> f = exp.Compile();
                T i = f.Invoke(this);
                return Observable.Return(new Tuple<T,string>(i,n));
            }
    
            public ViewModel()
            {
                PropertyChanged += ViewModel_PropertyChanged;
    //  Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(hh => hh.Invoke, h => this.PropertyChanged += h, h => this.PropertyChanged -= h)
                    .Subscribe((e) => { ViewModel_PropertyChanged(this, e.EventArgs); });
            }
    
            private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
    // From Event Pattern does not need subscribe again. Direct call Server side is enougth.
                if (e.PropertyName == "Cusip")
                    OnSubmitChanges(vm => vm.Cusip).Subscribe((i) => { Console.WriteLine("Call IVMController->IModObsAdapter->IModObsTransport->QueueAsObserver " + i); }); //459200-10-1 //912828NB2
                if (e.PropertyName == "Ask")
                    OnSubmitChanges(vm => vm.Ask).Subscribe((i) => { Console.WriteLine("Hit bid lift offer " + i); });
    
            }
        }
    
    
            private static void TestConvertPropChangeToObservable()
            {
                ViewModel v = new ViewModel();
                v.Cusip = "912828NB2";
                v.OnSubmitChanges(vm => vm.Cusip).Subscribe((i) => { Console.WriteLine("Call IVMController->IModObsAdapter->IModObsTransport->QueueAsObserver " + i); }); //459200-10-1 //912828NB2
                v.Ask = 98.23;
                v.OnSubmitChanges(vm => vm.Ask).Subscribe((i) => { Console.WriteLine("Hit bid lift offer " + i); }); 
    
            }
    

    Sunday, June 22, 2014

    F# Async through Agent= inbox as Queue

    Agent are mailbox and can run async block, similar to run a async block inside a function.
    
    
    
    
    open System
    open System.Net 
    open Microsoft.FSharp.Control.WebExtensions 
    open System.Diagnostics 
    open System.IO 
    
    
    let urlList= ["cnn" , "http://www.cnn.com"
                  "china", "http://www.china.com"
                 ]
    
    
    let fetch( url :string) = 
            let uri = new Uri(url)
            let c = new WebClient()
            let html =c.DownloadString(uri)
            printfn "%s" html
    
    let fetchAsync(n: string, url :string) = 
        async {
            let uri = new Uri(url)
            let c = new WebClient()
            let! html =c.AsyncDownloadString(uri)
            printfn "%s" html
        }
    
    let runAsync() =
        urlList 
        |> Seq.map fetchAsync
        |> Async.Parallel 
        |> Async.RunSynchronously 
    
    let runSync() = 
        "http://www.cnn.com"
        |> fetch
    
    
    let s= new StreamWriter("c:\working\1.txt",true)
    s.AutoFlush <-true
    let agent =
        MailboxProcessor.Start( fun inbox ->
         async {    while true do
                    let! msg =inbox.Receive()
                   // fetch(msg)
                    s.WriteLine(DateTime.Now.ToString()+ " "+msg);
                    })
    
    
    []
    let main arg =
        runSync()
        fetch("http://www.cnn.com")
        
        runAsync() |> ignore
     
        agent.Post("http://www.cnn.com")
        agent.Post("http://www.china.com")
        agent.Post("http://www.goolge.com")
        agent.Post("http://www.fb.com")
        let mutable b=true
        let mutable n=1
        Console.ReadLine() |> ignore
        while b do
            n<-n+1
            if n>1000 then
                b <-false
            agent.Post(n.ToString())
    
        Console.ReadLine() |> ignore
        s.Close()
        0
    
        
    
    
    
    

    Tuesday, April 22, 2014

    Generate Observables

    
        class Program
        {
            static void Main(string[] args)
            {
                DateTime dtStart = DateTime.Now;
                var txns = GenerateObservable<Transaction>(3, dt => new Transaction() { id = "txn " + dt.ToString() }, 3, dt => dt < dtStart.AddSeconds(120));
                var bsds = GenerateObservable<Transaction>(1, dt => new BondStaticData() { id = "bsd " + dt.ToString() }, 3, dt => dt < dtStart.AddSeconds(10));
    
                txns.CombineLatest(bsds,(t,b)=> t.id+" "+b.id).Subscribe(s=>Console.WriteLine(s));
    
                Console.ReadLine();
            }
    
            static IObservable GenerateObservable<T>(int seconds4Iteration, Func<DateTime,T> newT, int nextInSeconds,Func<DateTime,bool> continuation)
            {
                DateTime dtStart = DateTime.Now;
                return Observable.Generate(dtStart, continuation, dt => dt.AddSeconds(seconds4Iteration), newT, dt => TimeSpan.FromSeconds(nextInSeconds));
            }
        }
    

    Tuesday, March 18, 2014

    Await a Task Completion Source Task for Async Data

    
    

    The following can be modified to use yield return and observables
     private async void Button_Click(object sender, RoutedEventArgs e)
            {
                await Test();
            }
            Task Test()
            {
                WebClient w = new WebClient();
                return w.DownloadStringTaskAsync("");
            }

            Task RunCodeBlockAsync()
            {
                var tcs = new TaskCompletionSource();
                WebClient w = new WebClient();
                w.DownloadStringCompleted +=
                    (_, args) =>
                    {
                        tcs.SetResult(args.Result);
                    };
                return tcs.Task;
            }