Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Expanding on what rayburns said here is how I'm using STAthread, WPF and Asp.net WebApi. I used the parallel's extensions, specifically this file below.</p> <pre><code>//-------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: StaTaskScheduler.cs // //-------------------------------------------------------------------------- using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; namespace System.Threading.Tasks.Schedulers { public static class ParallelExtensions { public static Task StartNew(this TaskFactory factory, Action action, TaskScheduler scheduler) { return factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, scheduler); } public static Task&lt;TResult&gt; StartNew&lt;TResult&gt;(this TaskFactory factory, Func&lt;TResult&gt; action, TaskScheduler scheduler) { return factory.StartNew&lt;TResult&gt;(action, CancellationToken.None, TaskCreationOptions.None, scheduler); } public static Task&lt;TResult&gt; StartNewSta&lt;TResult&gt;(this TaskFactory factory, Func&lt;TResult&gt; action) { return factory.StartNew&lt;TResult&gt;(action, sharedScheduler); } private static TaskScheduler sharedScheduler = new StaTaskScheduler(1); } /// &lt;summary&gt;Provides a scheduler that uses STA threads.&lt;/summary&gt; public sealed class StaTaskScheduler : TaskScheduler, IDisposable { /// &lt;summary&gt;Stores the queued tasks to be executed by our pool of STA threads.&lt;/summary&gt; private BlockingCollection&lt;Task&gt; _tasks; /// &lt;summary&gt;The STA threads used by the scheduler.&lt;/summary&gt; private readonly List&lt;Thread&gt; _threads; /// &lt;summary&gt;Initializes a new instance of the StaTaskScheduler class with the specified concurrency level.&lt;/summary&gt; /// &lt;param name="numberOfThreads"&gt;The number of threads that should be created and used by this scheduler.&lt;/param&gt; public StaTaskScheduler(int numberOfThreads) { // Validate arguments if (numberOfThreads &lt; 1) throw new ArgumentOutOfRangeException("concurrencyLevel"); // Initialize the tasks collection _tasks = new BlockingCollection&lt;Task&gt;(); // Create the threads to be used by this scheduler _threads = Enumerable.Range(0, numberOfThreads).Select(i =&gt; { var thread = new Thread(() =&gt; { // Continually get the next task and try to execute it. // This will continue until the scheduler is disposed and no more tasks remain. foreach (var t in _tasks.GetConsumingEnumerable()) { TryExecuteTask(t); } }); thread.IsBackground = true; thread.SetApartmentState(ApartmentState.STA); return thread; }).ToList(); // Start all of the threads _threads.ForEach(t =&gt; t.Start()); } /// &lt;summary&gt;Queues a Task to be executed by this scheduler.&lt;/summary&gt; /// &lt;param name="task"&gt;The task to be executed.&lt;/param&gt; protected override void QueueTask(Task task) { // Push it into the blocking collection of tasks _tasks.Add(task); } /// &lt;summary&gt;Provides a list of the scheduled tasks for the debugger to consume.&lt;/summary&gt; /// &lt;returns&gt;An enumerable of all tasks currently scheduled.&lt;/returns&gt; protected override IEnumerable&lt;Task&gt; GetScheduledTasks() { // Serialize the contents of the blocking collection of tasks for the debugger return _tasks.ToArray(); } /// &lt;summary&gt;Determines whether a Task may be inlined.&lt;/summary&gt; /// &lt;param name="task"&gt;The task to be executed.&lt;/param&gt; /// &lt;param name="taskWasPreviouslyQueued"&gt;Whether the task was previously queued.&lt;/param&gt; /// &lt;returns&gt;true if the task was successfully inlined; otherwise, false.&lt;/returns&gt; protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { // Try to inline if the current thread is STA return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA &amp;&amp; TryExecuteTask(task); } /// &lt;summary&gt;Gets the maximum concurrency level supported by this scheduler.&lt;/summary&gt; public override int MaximumConcurrencyLevel { get { return _threads.Count; } } /// &lt;summary&gt; /// Cleans up the scheduler by indicating that no more tasks will be queued. /// This method blocks until all threads successfully shutdown. /// &lt;/summary&gt; public void Dispose() { if (_tasks != null) { // Indicate that no new tasks will be coming in _tasks.CompleteAdding(); // Wait for all threads to finish processing tasks foreach (var thread in _threads) thread.Join(); // Cleanup _tasks.Dispose(); _tasks = null; } } } } </code></pre> <p>Usage is pretty easy. Just use the code below to use the extension</p> <pre><code> Task&lt;MemoryStream&gt; Task1 = Task.Factory.StartNewSta(() =&gt; { /* use wpf here*/ BitmapEncoder PngEncoder = new PngBitmapEncoder(); PngEncoder.Frames.Add(BitmapFrame.Create(Render)); //save to memory stream var Ms = new MemoryStream(); PngEncoder.Save(Ms); return Ms; }); Task.WaitAll(Task1); return Task1.Result; </code></pre>
    singulars
    1. This table or related slice is empty.
    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. 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.
    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