(NET) NET (2015)

Building TreeView by Reactive Extensions NET (Recursive observe directory, Iterator function with Yield, Windows native thread).

На цієї сторінці буде описаний невеличкий приклад практичного застосування Reactive Extensions to .Net, для початку лінки на документацію на нього:

Це немаленька бібліотека, яка компілюється у специфічну StateMachine, яка виконує операції MoveNext у багатьох потоках одночасно. На цьому коді нище працює чотири потока .NET, у кожному з яких виконується YIELD.



Ця прога просто обходить файлову структуру, як будь-яка прога у моему блозі, наприклад ось ця - WinDump - снимок состояния системы с помощью WMI, але вона робіть це мультипоточно. І заповнює результатом обхода файлової системи Win-контрол TreeView.



Сподіваюсь, смисл цього коду зрозумілий. Дві змінні, які задані у стрічках 21 та 26, мають евенти, які додають до них бібліотека System.Reactive.DLL. На ці євенти підписуються у стрічках 73 та 84 хандлер outputDirectories або outputDirectory. Коли з'являється перший підписник, тоді сам RX викликає хєндлер GetAllDirectories, заданий у стрічках 137 і далі, який працює у мультипоточному режимі.


   1:  Imports System.Reactive.Concurrency
   2:  Imports System.Reactive.Linq
   3:  Imports System.Threading
   4:  Imports System.Collections.Generic
   5:  Imports System.ComponentModel
   6:  Imports System.Data
   7:  Imports System.Drawing
   8:  Imports System.Linq
   9:  Imports System.Text
  10:  Imports System.Windows.Forms
  11:  Imports System.IO
  12:   
  13:  ''' <summary>
  14:  ''' Provides an example of using the RxFramework to get directory listings using a background thread.
  15:  ''' </summary>
  16:  Partial Public Class DirectoriesForm
  17:   
  18:      ''' <summary>
  19:      ''' An observable providing a directory as soon as it is encountered.
  20:      ''' </summary>
  21:      Private directories As IObservable(Of String)
  22:   
  23:      ''' <summary>
  24:      ''' An observable providing directories in groups.
  25:      ''' </summary>
  26:      Private bufferedDirectories As IObservable(Of IList(Of String))
  27:   
  28:      ''' <summary>
  29:      ''' The current observer that is observing on one of the observables.
  30:      ''' </summary>
  31:      Private observer As IDisposable
  32:   
  33:      Public Sub New()
  34:          InitializeComponent()
  35:   
  36:          Dim syncContext = SynchronizationContext.Current
  37:   
  38:          ' Observe the enumeration of all directories using the winforms thread.
  39:          Me.directories = GetAllDirectories("c:\").
  40:              ToObservable(Scheduler.ThreadPool).
  41:              ObserveOn(syncContext)
  42:   
  43:          ' Observe the enumeratino of all directories, but buffered in groups 
  44:          ' of 1000 entries each second, and then observe that group on the winforms thread.
  45:          Me.bufferedDirectories = Observable.
  46:              Interval(TimeSpan.FromSeconds(1), Scheduler.ThreadPool).
  47:              Zip(
  48:              GetAllDirectories("c:\").
  49:              ToObservable(Scheduler.ThreadPool).
  50:              Buffer(1000),
  51:              Function(a, b) b
  52:              ).
  53:              ObserveOn(syncContext)
  54:   
  55:          Me.butStop.Enabled = False
  56:      End Sub
  57:   
  58:      Private Sub butStop_Click(sender As Object, e As EventArgs) Handles butStop.Click
  59:          ' Clear out the running observer
  60:          If Me.observer IsNot Nothing Then
  61:              Me.observer.Dispose()
  62:              Me.observer = Nothing
  63:              Me.butStop.Enabled = False
  64:              Me.butObserverSingle.Enabled = True
  65:              Me.butObserveBuffered.Enabled = True
  66:          End If
  67:      End Sub
  68:   
  69:      Private Sub butObserverSingle_Click(sender As Object, e As EventArgs) Handles butObserverSingle.Click
  70:          Me.treeViewDirectories.Nodes.Clear()
  71:          If Me.observer Is Nothing Then
  72:              ' Observe on the single directories.
  73:              Me.observer = Me.directories.Subscribe(AddressOf outputDirectory)
  74:              Me.butStop.Enabled = True
  75:              Me.butObserverSingle.Enabled = False
  76:              Me.butObserveBuffered.Enabled = False
  77:          End If
  78:      End Sub
  79:   
  80:      Private Sub butObserveBuffered_Click(sender As Object, e As EventArgs) Handles butObserveBuffered.Click
  81:          Me.treeViewDirectories.Nodes.Clear()
  82:          If Me.observer Is Nothing Then
  83:              ' observe on the buffered directories.
  84:              Me.observer = Me.bufferedDirectories.Subscribe(AddressOf outputDirectories)
  85:              Me.butStop.Enabled = True
  86:              Me.butObserverSingle.Enabled = False
  87:              Me.butObserveBuffered.Enabled = False
  88:          End If
  89:      End Sub
  90:   
  91:      Private Sub outputDirectory(path As String)
  92:          ' We check to see if the handle is created because when 
  93:          ' the form is disposing this may still be trying to observe.
  94:          If Me.treeViewDirectories.IsHandleCreated Then
  95:              Me.treeViewDirectories.Nodes.Add(path)
  96:          End If
  97:      End Sub
  98:   
  99:      Private treeNodes As New Dictionary(Of String, TreeNode)()
 100:   
 101:      Private Sub outputDirectories(paths As IEnumerable(Of String))
 102:          ' We check to see if the handle is created because when 
 103:          ' the form is disposing this may still be trying to observe.
 104:          If Me.treeViewDirectories.IsHandleCreated Then
 105:              Try
 106:                  Me.treeViewDirectories.BeginUpdate()
 107:                  For Each path__1 In paths
 108:                      Dim sb = New StringBuilder()
 109:                      Dim pieces = path__1.Split(Path.DirectorySeparatorChar)
 110:                      Dim parent As TreeNode = Nothing
 111:                      For i As Integer = 0 To pieces.Length - 1
 112:                          Dim child As TreeNode = Nothing
 113:                          sb.Append(pieces(i))
 114:                          sb.Append(Path.DirectorySeparatorChar)
 115:   
 116:                          If Not treeNodes.TryGetValue(sb.ToString(), child) Then
 117:                              If parent IsNot Nothing Then
 118:                                  child = parent.Nodes.Add(pieces(i))
 119:                              Else
 120:                                  child = Me.treeViewDirectories.Nodes.Add(pieces(i))
 121:                              End If
 122:                              treeNodes(sb.ToString()) = child
 123:                          End If
 124:                          parent = child
 125:                      Next
 126:                  Next
 127:              Finally
 128:                  Me.treeViewDirectories.EndUpdate()
 129:              End Try
 130:          End If
 131:      End Sub
 132:      ''' <summary>
 133:      ''' Gets the enumeratino of all directories and sub directories under the given path.
 134:      ''' </summary>
 135:      ''' <param name="path">The path to search</param>
 136:      ''' <returns>The enumeration of all directories and sub directories.</returns>
 137:      Private Shared Iterator Function GetAllDirectories(path As String) As IEnumerable(Of String)
 138:          Dim subdirs As String() = Nothing
 139:          ' Some directories may be inaccessable.
 140:          Try
 141:              subdirs = Directory.GetDirectories(path)
 142:          Catch generatedExceptionName As IOException
 143:          Catch generatedExceptionName As UnauthorizedAccessException
 144:          End Try
 145:          If subdirs IsNot Nothing Then
 146:              For Each subdir In subdirs
 147:                  Debug.Print(subdir.ToString)
 148:                  Yield subdir
 149:                  For Each grandchild In GetAllDirectories(subdir)
 150:                      Debug.Print(grandchild.ToString)
 151:                      Yield grandchild
 152:                  Next
 153:              Next
 154:          End If
 155:      End Function
 156:   
 157:  End Class

Modern version of this library:




Comments ( )
Link to this page: //www.vb-net.com/TreeView-ReactiveExtensionsNET/index.htm
< THANKS ME>