Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>With the later .Net Frameworks (4.0+) and WPF you can utilize the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.aspx" rel="nofollow"><code>System.Threading.Tasks</code></a> library to provide a lot of this work under the hood.</p> <p>If say your Command on your needs to update a property on your View Model, but it has to wait for the information, you simply start a task to perform the IO:</p> <pre><code>this.FindDataCommand = new RelayCommand&lt;string&gt;( /* ICommand.Execute */ value =&gt; { Task.Factory .StartNew&lt;IEnumerable&lt;Foo&gt;&gt;(() =&gt; FindData(value)) .ContinueWith( task =&gt; { this.foundData.Clear(); this.foundData.AddRange(task.Result); }, TaskScheduler.FromCurrentSynchronizationContext()); }, /* ICommand.CanExecute */ value =&gt; !String.IsNullOrWhitespace(value)); </code></pre> <p>Breaking this down into manageable parts, we're <a href="http://msdn.microsoft.com/en-us/library/dd321421.aspx" rel="nofollow">starting a new task</a> which calls some method <code>IEnumerable&lt;Foo&gt; FindData(string)</code>. This is the plain old boring synchronous code you've always written. Likely it already exists on your view model!</p> <p>Next we tell the framework to <a href="http://msdn.microsoft.com/en-us/library/dd270696.aspx" rel="nofollow">start a new task when that one finishes</a> using <code>ContinueWith</code>, but to do it on the <a href="http://blog.lab49.com/archives/4034" rel="nofollow">WPF Dispatcher instead</a>. This allows you to avoid the hassles of cross-thread problems with UI elements.</p> <p>You can extend this for monitoring with a helper class:</p> <pre><code>public class TaskManager { private static ConcurrentDictionary&lt;Dispatcher, TaskManager&gt; _map = new ConcurrentDictionary&lt;Dispatcher, TaskManager&gt;(); public ObservableCollection&lt;WorkItem&gt; Running { get; private set; } public TaskManager() { this.Running = new ObservableCollection&lt;WorkItem&gt;(); } public static TaskManager Get(Dispatcher dispatcher) { return _map.GetOrAdd(dispatcher, new TaskManager()); } // ... </code></pre> <p>Using this class in XAML would be along the lines of adding its instance to your Window's <code>ViewModel</code>:</p> <pre><code>public TaskManager CurrentTaskManager { get { return TaskManager.Get(Dispatcher.CurrentDispatcher); } } // &lt;StatusBarItem Content="{Binding CurrentTaskManager.Running.Count}" /&gt; </code></pre> <p>You would then add a method to your TaskManager to handle the adding of tasks to and from the Running collection:</p> <pre><code> public Task&lt;TResult&gt; StartNew&lt;TResult&gt;(Func&lt;TResult&gt; work) { var task = Task.Factory .StartNew&lt;TResult&gt;(work); // build our view model var workItem = new WorkItem(task); this.Running.Add(workItem); // Pass the result back using ContinueWith return task.ContinueWith( t =&gt; { this.Running.Remove(workItem); return t.Result; }, TaskScheduler.FromCurrentSynchronizationContext()); } </code></pre> <p>Now we simply change our <code>FindDataCommand</code> implementation:</p> <pre><code>TaskManager.Get(Dispatcher.CurrentDispatcher) .StartNew&lt;IEnumerable&lt;Foo&gt;&gt;(() =&gt; FindData(value)) .ContinueWith( task =&gt; { this.foundData.Clear(); this.foundData.AddRange(task.Result); }, TaskScheduler.FromCurrentSynchronizationContext()); </code></pre> <p>The <code>WorkItem</code> class could expose the properties on the <code>Task</code> class to the UI, or it could be extended to encapsulate a <code>CancellationToken</code> to support cancellation in the future.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload