set clipboard in async method - c#

[STAThread]
static void Main(string[] args)
{
DoThing().Wait();
}
static async Task DoThing()
{
Clipboard.SetText("hi");
}
I added [STAThread] in the first place bc I got this error
ThreadStateException: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made
But I am still getting the same error.
Clipboard is from System.Windows.Forms.
How do I set the clipboard from that async method?

The issue is that async threads are run from the threadpool, and they are all MTA threads. Task.Run() also creates MTA threads.
You will have to explicitly start an STA thread to run the code. Here's a sample helper class:
public static class STATask
{
/// <summary>
/// Similar to Task.Run(), except this creates a task that runs on a thread
/// in an STA apartment rather than Task's MTA apartment.
/// </summary>
/// <typeparam name="TResult">The return type of the task.</typeparam>
/// <param name="function">The work to execute asynchronously.</param>
/// <returns>A task object that represents the work queued to execute on an STA thread.</returns>
public static Task<TResult> Run<TResult>([NotNull] Func<TResult> function)
{
var tcs = new TaskCompletionSource<TResult>();
var thread = new Thread(() =>
{
try
{
// Most usages will require a message pump, which can be
// started by calling Application.Run() at an appropriate point.
tcs.SetResult(function());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
/// <summary>
/// Similar to Task.Run(), except this creates a task that runs on a thread
/// in an STA apartment rather than Task's MTA apartment.
/// </summary>
/// <param name="action">The work to execute asynchronously.</param>
/// <returns>A task object that represents the work queued to execute on an STA thread.</returns>
public static Task Run([NotNull] Action action)
{
var tcs = new TaskCompletionSource<object>(); // Return type is irrelevant for an Action.
var thread = new Thread(() =>
{
try
{
action();
tcs.SetResult(null); // Irrelevant.
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
}
You could then implement DoThing() like this:
static async Task DoThing()
{
await STATask.Run(() => Clipboard.SetText("hi"));
}
Note that, as pointed out by Stephen Cleary, usually you need a message pump for an STA thread. You seem to be able to get away with this if you're just setting the clipboard text, but for anything more complicated you're likely to have to run a message pump in the thread.
The easiest way to run the message pump is via a call to Application.Run(), but you will have to handle the application context yourself.

Related

C# delegates to Java and asynchronous handling of methods

I have been tasked with creating Java code with similar functionality to the code below. Currently I am struggling with understanding exactly what the code does and how to simulate the effect in Java.
#region "Send Aggregate Event"
/// <summary>
/// Delegate for async sending the AggregateEvent
/// </summary>
/// <param name="request"></param>
public delegate void SendAggregateEventAsync(AE request);
SendAggregateEventAsync _sendAggregateEventAsync;
/// <summary>
/// IAsyncResult pattern to async send the AggregateEvent
/// </summary>
/// <param name="request"></param>
/// <param name="callback"></param>
/// <param name="state"></param>
/// <returns></returns>
public IAsyncResult BeginSendAggregateEvent(AE request, AsyncCallback callback, Object state)
{
_sendAggregateEventAsync = new SendAggregateEventAsync(SendAggregateEvent);
return _sendAggregateEventAsync.BeginInvoke(request, callback, state);
}
public void EndSendAggregateEvent(IAsyncResult result)
{
object state = result.AsyncState;
_sendAggregateEventAsync.EndInvoke(result);
}
/// <summary>
/// Send an aggregate event to the Device Webserver
/// </summary>
/// <param name="request">The AggregateEvent request</param>
public void SendAggregateEvent(AE request)
{
if (request == null) throw new ArgumentNullException("request");
String message = ChangeDatesToUTC(MessageHelper.SerializeObject( typeof(AE), request), new String[] { "EventTime" }, url);
SendMessage(message);
}
#endregion
There are several other events all with similar code to the provided above. From the comments, I understand that the code is intended to asynchronously handle the SendAggregateEvent method. What I do not understand is why the delegate modifier is used, or how to replicate this type of asynchronous handling in Java.
Also from reading this thread
Java Delegates?
I understand that there is no "easy" way to simulate the delegate functionality in java. Is it necessary to have the delegate functionality to have the SendAggregateEvent method handled asynchronously? If not, can someone suggest how I would do this?
This is actually the old way of writing async code in C#, commonly referred to as the Async Programming Model
I am not familiar enough with java, but all you really need to replicate this code is to create a method that does the action synchronously SendAggregateEvent and a means to call that asynchronously SendAggregateEventAsync
More specifically to some of your questions. The delegate is only being used to encapsulate the SendAggregateEvent method so that it and its parameters can be invoked on a potentially different thread (keeping in mind that async is not necessarily multi-threaded)
It goes something like this:
var referenceToTaskBeingRun = BeginSomeMethod()
//the above wraps the actual method and calls it, returning a reference to the task
var results = EndSomeMethod(referenceToTaskBeingRun );
//the above sends the reference so that it can be used to get the results from the task.
//NOTE that this is blocking because you are now waiting for the results, whether they finished or not
The preferred way to do this now is to use the Task Parallel Library, which has a much easier to read code base.
So, all of that being said, the key to focus on this code would be that you just need a method and an async version of that method. The implementation should be up to you and your programming stack. Do not try to force another stack's implementation where it does not belong...especially an implementation that is not even the preferred methodology any longer.
According to How to asynchronously call a method in Java's answer, FutureTask is a good way in Java to asynchronously run a method. Here's some Java code that runs a task asynchronously (see it run at http://ideone.com/ZtjA5C)
import java.util.*;
import java.lang.*;
import java.util.concurrent.FutureTask;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println("Before");
ExecutorService executorService = Executors.newFixedThreadPool(1);
FutureTask<Object> futureTask = new FutureTask<Object>(new Runnable() {
public void run()
{
System.out.println("Hello async world!");
}
}, null);
System.out.println("Defined");
executorService.execute(futureTask);
System.out.println("Running");
while (!futureTask.isDone())
{
System.out.println("Task not yet completed.");
try
{
Thread.sleep(1);
}
catch (InterruptedException interruptedException)
{
}
}
System.out.println("Done");
}
}

WatiN Parallelization within a test

I have a test where I want to ensure separate operations within one page result in distinct results. Specifically, I have a few ways to sort on a page and I want a test to make sure that each sort is different. I have other tests to ensure the correctness of each sort.
I would like the focus of this conversation to be on a good way to run test operations in parallel and compare the results at the end, rather than on what to test or testing methods. I figure parallel operations in testing is an interesting and broad enough topic that it could be useful to others.
Let "generateHashFromSearchResults()" be a function that returns a string representing the order of the search results shown on current IE instance. Here is what the working code looks like in a serialized fashion using one browser instance:
var set = new HashSet<string>();
var sortOptions = new List<String>() { "sort1", "sort2", "sort3" };
// Default sort
set.Add(generateHashFromSearchResults());
sortOptions.ForEach(s => {
ie.Link(Find.ByText(s)).Click();
set.Add(generateHashFromSearchResults());
});
Assert.That(set.Count() == 4);
I had read about PLINQ a few months ago and figured this might be a decent use case. Now let "generateHashFromSearchResults(IE ie)" be the same function, but that operates on an explicitly defined IE instance. I tried something like this:
List<string> resultList = sortOptions.AsParallel().Select(s => {
var ie = new IE(true);
ie.Link(Find.ByText(s)).Click();
return generateHashFromSearchResults(ie);
}).ToList();
// Forget about default sort for now. There should be 3 distinct results
Assert.That(new HashSet<string>(resultList).Count() == 3);
The biggest issue I face right now is not understanding how PLINQ does thread management. WatiN needs to run with the apartment state set to single threaded (STAThread). I get that each IE instance should be in its own thread, but no amount of setting each thread in the PLINQ query to the proper apartment state fixes the issue.
I'm starting to suspect that I either need to learn more about PLINQ to continue, or that I need to learn more about thread management by hand to get this to work.
Any thoughts?
You can't specify a custom scheduler with AsParallel(). But you can create a Task for each sort option and pass an instance of a custom scheduler into the Start() method. This implementation of an STA Thread scheduler was borrowed from Stephen Toub (http://blogs.msdn.com/b/pfxteam/archive/2010/04/07/9990421.aspx):
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Provides a scheduler that uses STA threads.
/// Borrowed from Stephen Toub's implementation http://blogs.msdn.com/b/pfxteam/archive/2010/04/07/9990421.aspx
/// </summary>
public sealed class StaTaskScheduler : TaskScheduler, IDisposable
{
/// <summary>
/// The STA threads used by the scheduler.
/// </summary>
private readonly List<Thread> threads;
/// <summary>
/// Stores the queued tasks to be executed by our pool of STA threads.
/// </summary>
private BlockingCollection<Task> tasks;
/// <summary>
/// Initializes a new instance of the StaTaskScheduler class with the specified concurrency level.
/// </summary>
/// <param name = "numberOfThreads">The number of threads that should be created and used by this scheduler.</param>
public StaTaskScheduler(int numberOfThreads)
{
if (numberOfThreads < 1)
{
throw new ArgumentOutOfRangeException(
"numberOfThreads", "The scheduler must create at least one thread");
}
// Initialize the tasks collection
this.tasks = new BlockingCollection<Task>();
// Create the threads to be used by this scheduler
this.threads = Enumerable.Range(0, numberOfThreads).Select(
i =>
{
var thread = new Thread(
() =>
{
// Continually get the next task and try to execute it.
// This will continue until the scheduler is disposed and no more tasks remain.
foreach (Task t in this.tasks.GetConsumingEnumerable())
{
this.TryExecuteTask(t);
}
}) {
Name = "Sta Thread", IsBackground = true
};
thread.SetApartmentState(ApartmentState.STA);
return thread;
}).ToList();
// Start all of the threads
this.threads.ForEach(t => t.Start());
}
/// <summary>
/// Gets the maximum concurrency level supported by this scheduler.
/// </summary>
public override int MaximumConcurrencyLevel
{
get
{
return this.threads.Count;
}
}
/// <summary>
/// Cleans up the scheduler by indicating that no more tasks will be queued.
/// This method blocks until all threads successfully shutdown.
/// </summary>
public void Dispose()
{
if (this.tasks != null)
{
// Indicate that no new tasks will be coming in
this.tasks.CompleteAdding();
// Wait for all threads to finish processing tasks
foreach (Thread thread in this.threads)
{
thread.Join();
}
// Cleanup
this.tasks.Dispose();
this.tasks = null;
}
}
/// <summary>
/// Provides a list of the scheduled tasks for the debugger to consume.
/// </summary>
/// <returns>An enumerable of all tasks currently scheduled.</returns>
protected override IEnumerable<Task> GetScheduledTasks()
{
// Serialize the contents of the blocking collection of tasks for the debugger
return this.tasks.ToArray();
}
/// <summary>
/// Queues a Task to be executed by this scheduler.
/// </summary>
/// <param name = "task">The task to be executed.</param>
protected override void QueueTask(Task task)
{
// Push it into the blocking collection of tasks
this.tasks.Add(task);
}
/// <summary>
/// Determines whether a Task may be inlined.
/// </summary>
/// <param name = "task">The task to be executed.</param>
/// <param name = "taskWasPreviouslyQueued">Whether the task was previously queued.</param>
/// <returns>true if the task was successfully inlined; otherwise, false.</returns>
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
// Try to inline if the current thread is STA
return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA && this.TryExecuteTask(task);
}
}
Maybe You should use Task Parallel Library?
I'm a beginner in TPL, but there are Schedulers that maybe have some options for setting STAThread on scheduled Tasks.

Best solution for a windows service with constant running threads in C# 4.0

I want to create a windows service that will create x number of threads that wake up every x number of minutes and do some work.
I think the task scheduling or parallel framework is a bad fit for this type of work as it is best suited for work that starts, completes and finishes rather than is constant.
Should I look at utilising a thread pool for this approach or does anyone have any advice for a good solution?
Really, it sounds like you only need one thread.
Here's a helper class that I created for exactly this kind of thing. Here's how you use it:
class MyPeriodicTasks : PeriodicMultiple
{
// The first task will start 30 seconds after this class is instantiated and started:
protected override TimeSpan FirstInterval { get { return TimeSpan.FromSeconds(30); } }
public MyPeriodicTasks()
{
Tasks = new[] {
new Task { Action = task1, MinInterval = TimeSpan.FromMinutes(5) },
new Task { Action = task2, MinInterval = TimeSpan.FromMinutes(15) },
};
}
private void task1() { /* code that gets executed once every 5 minutes */ }
private void task2() { /* code that gets executed once every 15 minutes */ }
}
Then, to start the tasks:
var tasks = new MyPeriodicTasks();
tasks.Start();
And during service shutdown:
tasks.Shutdown();
(alternatively, call Start with backgroundThread: true, then you don't need to call Shutdown, but then a task may just get terminated right in the middle of doing something)
Here's the actual code:
/// <summary>
/// Encapsulates a class performing a certain activity periodically, which can be initiated once
/// and then permanently shut down, but not paused/resumed. The class owns its own separate
/// thread, and manages this thread all by itself. The periodic task is executed on this thread.
/// <para>The chief differences to <see cref="System.Threading.Timer"/> are as follows. This
/// class will never issue overlapping activities, even if an activity takes much longer than the interval;
/// the interval is between the end of the previous occurrence of the activity and the start of the next.
/// The activity is executed on a foreground thread (by default), and thus will complete once started,
/// unless a catastrophic abort occurs. When shutting down the activity, it's possible to wait until the
/// last occurrence, if any, has completed fully.</para>
/// </summary>
public abstract class Periodic
{
private Thread _thread;
private CancellationTokenSource _cancellation;
private ManualResetEvent _exited;
/// <summary>
/// Override to indicate how long to wait between the call to <see cref="Start"/> and the first occurrence
/// of the periodic activity.
/// </summary>
protected abstract TimeSpan FirstInterval { get; }
/// <summary>
/// Override to indicate how long to wait between second and subsequent occurrences of the periodic activity.
/// </summary>
protected abstract TimeSpan SubsequentInterval { get; }
/// <summary>
/// Override with a method that performs the desired periodic activity. If this method throws an exception
/// the thread will terminate, but the <see cref="LastActivity"/> will occur nevertheless.
/// </summary>
protected abstract void PeriodicActivity();
/// <summary>
/// Override with a method that performs an activity on the same thread as <see cref="PeriodicActivity"/> during
/// shutdown, just before signalling that the shutdown is complete. The default implementation of this method
/// does nothing. This method is guaranteed to be called during a shutdown, even if the shutdown is due to an
/// exception propagating outside of <see cref="PeriodicActivity"/>.
/// </summary>
protected virtual void LastActivity() { }
/// <summary>
/// Returns false before the first call to <see cref="Start"/> and after the first call to <see cref="Shutdown"/>;
/// true between them.
/// </summary>
public bool IsRunning { get { return _cancellation != null && !_cancellation.IsCancellationRequested; } }
/// <summary>
/// Schedules the periodic activity to start occurring. This method may only be called once.
/// </summary>
/// <param name="backgroundThread">By default (false) the class will use a foreground thread, preventing application shutdown until the thread has terminated. If true, a background thread will be created instead.</param>
public virtual void Start(bool backgroundThread = false)
{
if (_thread != null)
throw new InvalidOperationException(string.Format("\"Start\" called multiple times ({0})", GetType().Name));
_exited = new ManualResetEvent(false);
_cancellation = new CancellationTokenSource();
_thread = new Thread(threadProc) { IsBackground = backgroundThread };
_thread.Start();
}
private volatile bool _periodicActivityRunning = false;
/// <summary>
/// Causes the periodic activity to stop occurring. If called while the activity is being performed,
/// will wait until the activity has completed before returning. Ensures that <see cref="IsRunning"/>
/// is false once this method returns.
/// </summary>
public virtual bool Shutdown(bool waitForExit)
{
if (waitForExit && _periodicActivityRunning && Thread.CurrentThread.ManagedThreadId == _thread.ManagedThreadId)
throw new InvalidOperationException("Cannot call Shutdown(true) from within PeriodicActivity() on the same thread (this would cause a deadlock).");
if (_cancellation == null || _cancellation.IsCancellationRequested)
return false;
_cancellation.Cancel();
if (waitForExit)
_exited.WaitOne();
return true;
}
private void threadProc()
{
try
{
_cancellation.Token.WaitHandle.WaitOne(FirstInterval);
while (!_cancellation.IsCancellationRequested)
{
_periodicActivityRunning = true;
PeriodicActivity();
_periodicActivityRunning = false;
_cancellation.Token.WaitHandle.WaitOne(SubsequentInterval);
}
}
finally
{
try { LastActivity(); }
finally { _exited.Set(); }
}
}
}
/// <summary>
/// <para>Encapsulates a class performing multiple related yet independent tasks on the same thread
/// at a certain minimum interval each. Schedules the activity that is the most late at every opportunity,
/// but will never execute more than one activity at a time (as they all share the same thread).</para>
/// </summary>
public abstract class PeriodicMultiple : Periodic
{
/// <summary>
/// Used to define the activities to be executed periodically.
/// </summary>
protected sealed class Task
{
/// <summary>The activity to be performed.</summary>
public Action Action;
/// <summary>The mimimum interval at which this activity should be repeated. May be delayed arbitrarily though.</summary>
public TimeSpan MinInterval;
/// <summary>Stores the last time this activity was executed.</summary>
public DateTime LastExecuted;
/// <summary>Calculates by how much this activity has been delayed. Is used internally to pick the next activity to run. Returns negative values for activities that aren't due yet.</summary>
public TimeSpan DelayedBy()
{
if (LastExecuted == default(DateTime))
return TimeSpan.FromDays(1000) - MinInterval; // to run shortest interval first when none of the tasks have ever executed
else
return (DateTime.UtcNow - LastExecuted) - MinInterval;
}
}
/// <summary>If desired, override to provide a custom interval at which the scheduler
/// should re-check whether any activity is due to start. Defaults to 1 second.</summary>
protected override TimeSpan SubsequentInterval { get { return TimeSpan.FromSeconds(1); } }
/// <summary>Initialise this with the list of activities to be executed.</summary>
protected IList<Task> Tasks;
/// <summary>For internal use.</summary>
protected sealed override void PeriodicActivity()
{
TimeSpan maxDelay = TimeSpan.MinValue;
Task maxDelayTask = null;
foreach (var task in Tasks)
{
var delayedBy = task.DelayedBy();
if (maxDelay < delayedBy && delayedBy > TimeSpan.Zero)
{
maxDelay = delayedBy;
maxDelayTask = task;
}
}
if (maxDelayTask != null)
{
maxDelayTask.LastExecuted = DateTime.UtcNow;
maxDelayTask.Action();
}
}
}
The thread spends most of the time sleeping, but it does wake up every 1 second to check if a task is due. This 1 second interval is probably too short for intervals like 15 minutes, so reduce it to something like 30 seconds instead (that would be the SubsequentInterval).
Hope it's useful!
It makes very little sense to start x threads to do x jobs when you intentionally don't let them do any work at all for y minutes. Just have one thread do x jobs. It will take x times longer to complete the work (a bit less, actually) but that's no issue at all as long as that takes less than y minutes.
Additional benefits from this is that the service cannot easily impact the responsiveness of the machine, other cores remain available. And that your code becomes a heckofalot easier to implement and debug.
Use the System.Threading.Thread timer to activate the work. The callback runs on a threadpool thread. Starting and stopping the service is easy, just enable/disable that timer.
Do you really need those threads to run constantly and then wake up after x minutes? I think you may want to consider using an existing scheduler library like Quartz.NET which handle running the tasks for you.
I have two suggestions for you. First, for building your service, check out TopShelf. It removes all the pain of setting up a Windows service.
Second, you can use the Observable class to create a timer without resorting to writing Timer specific code or Quartz (a pain to configure!).
Here's some sample code:
public class MyService
{
private IDisposable Timer;
public void Start()
{
Timer = ObservableHelpers
.CreateMinutePulse(15) // check every 15 seconds if it's a new minute
.Subscribe(i => DoSomething());
}
public void Stop()
{
if(Timer != null)
{
Timer.Dispose();
Timer = null;
}
}
public void DoSomething()
{
// do your thing here
}
}
public static class ObservableHelpers
{
/// <summary>
/// Returns an observable that pulses every minute with the specified resolution.
/// The pulse occurs within the amount of time specified by the resolution (in seconds.)
/// Higher resolution (i.e. lower specified number of seconds) may affect execution speed.
/// </summary>
/// <returns></returns>
public static IObservable<int> CreateMinutePulse(int resolution)
{
return Observable
.Interval(TimeSpan.FromSeconds(resolution.SetWithinRange(1, 59)))
.Select(i => DateTime.Now.Minute)
.DistinctUntilChanged();
}
}
Well, I belive your problem seems to be solved with Producer Consumer Design pattern.
Producer will be the single main thread, and the all other threads will be the consumer thread.
From my opinion it will be best have independent threads than using thread pool.
Eg:
private Thread Worker;
public Consumer()
{
Worker = new Thread(ProcessMethod);
}
Now in processmethod you do what you have to do.
Create as many Consumer as you want.

Serial Task Executor; is this thread safe?

I have a class that I've created to allow asynchronous sequential execution of tasks, using the ThreadPool as the means of execution. The idea is that I'll have multiple instances running serial tasks in the background, but I don't want to have a separate dedicated Thread for each instance. What I'd like to check is whether this class is actually thread safe. It's fairly brief, so I thought I'd run it by the experts here, in case I'm missing something obvious. I've omitted a few of the convenience overloads for different Action types.
/// <summary>
/// This class wraps ThreadPool.QueueUserWorkItem, but providing guaranteed ordering of queued tasks for this instance.
/// Only one task in the queue will execute at a time, with the order of execution matching the order of addition.
/// This is designed as a lighter-weight alternative to using a dedicated Thread for processing of sequential tasks.
/// </summary>
public sealed class SerialAsyncTasker
{
private readonly Queue<Action> mTasks = new Queue<Action>();
private bool mTaskExecuting;
/// <summary>
/// Queue a new task for asynchronous execution on the thread pool.
/// </summary>
/// <param name="task">Task to execute</param>
public void QueueTask(Action task)
{
if (task == null) throw new ArgumentNullException("task");
lock (mTasks)
{
bool isFirstTask = (mTasks.Count == 0);
mTasks.Enqueue(task);
//Only start executing the task if this is the first task
//Additional tasks will be executed normally as part of sequencing
if (isFirstTask && !mTaskExecuting)
RunNextTask();
}
}
/// <summary>
/// Clear all queued tasks. Any task currently executing will continue to execute.
/// </summary>
public void Clear()
{
lock (mTasks)
{
mTasks.Clear();
}
}
/// <summary>
/// Wait until all currently queued tasks have completed executing.
/// If no tasks are queued, this method will return immediately.
/// This method does not prevent the race condition of a second thread
/// queueing a task while one thread is entering the wait;
/// if this is required, it must be synchronized externally.
/// </summary>
public void WaitUntilAllComplete()
{
lock (mTasks)
{
while (mTasks.Count > 0 || mTaskExecuting)
Monitor.Wait(mTasks);
}
}
private void RunTask(Object state)
{
var task = (Action)state;
task();
mTaskExecuting = false;
RunNextTask();
}
private void RunNextTask()
{
lock (mTasks)
{
if (mTasks.Count > 0)
{
mTaskExecuting = true;
var task = mTasks.Dequeue();
ThreadPool.QueueUserWorkItem(RunTask, task);
}
else
{
//If anybody is waiting for tasks to be complete, let them know
Monitor.PulseAll(mTasks);
}
}
}
}
UPDATE: I've revised the code to fix the main bugs kindly pointed out by Simon. This passes unit tests now, but I still welcome observations.
Don't do it. (Or at least avoid building your own stuff.)
Use the System.Threading.Tasks stuff (new in .NET 4.0). Create your a Task[] (size depends on number of parallel tasks you want) and let them read work items from a BlockingCollection while waiting for a CancellationToken. Your WaitForAll implementation would trigger your token, and call Task.WaitAll(Task[]) which will block until all your tasks are done.
Here's my second answer assuming that you cant use .NET 4.0 (and want comments on your existing code).
QueueTask enqueues the first task, getting isFirstTask = true, and starts a new thread. However, another thread may enqueue something while the first thread is processing, and Count == 0 => isFirstTask = true, and yet another thread is spawned.
Also, WaitUntilAllComplete will hang indefinitely if the task execution throws an exception (which may not necessarily crash everything, depending on exception handling), causing it to skip the call to RunNextTask().
And your WaitUntilAllComplete just waits until there are no more enqueue tasks, not that those currently executing are actually executing (they could just be enqueued in the ThreadPool) or complete.
It's built in in 4.0
How to: Create a Task Scheduler That Limits the Degree of Concurrency
You can also use a custom scheduler to achieve functionality that the default scheduler does not provide, such as strict first-in, first-out (FIFO) execution order. The following example demonstrates how to create a custom task scheduler. This scheduler lets you specify the degree of concurrency.
I see a few issues your with your SerialAsyncTasker class, but it sounds like you might have a good grasp of those so I will not go into any details on that topic (I may edit my answer with more details later). You indicated in the comments that you cannot use .NET 4.0 features nor can you use the Reactive Extensions backport. I propose that you use the producer-consumer pattern with a single consumer on a dedicated thread. This would perfectly fit your requirement of asynchronously executing tasks sequentially.
Note: You will have to harden the code to support gracefully shutting down, handling exceptions, etc.
public class SerialAsyncTasker
{
private BlockingCollection<Action> m_Queue = new BlockingCollection<Action>();
public SerialAsyncTasker()
{
var thread = new Thread(
() =>
{
while (true)
{
Action task = m_Queue.Take();
task();
}
});
thread.IsBackground = true;
thread.Start();
}
public void QueueTask(Action task)
{
m_Queue.Add(task);
}
}
Too bad you cannot use the BlockingCollection from the .NET 4.0 BCL or Reactive Extension download, but no worries. It is actually not too hard to implement one yourself. You can use Stephen Toub's blocking queue as a starting point and just rename a few things.
public class BlockingCollection<T>
{
private Queue<T> m_Queue = new Queue<T>();
public T Take()
{
lock (m_Queue)
{
while (m_Queue.Count <= 0) Monitor.Wait(m_Queue);
return m_Queue.Dequeue();
}
}
public void Add(T value)
{
lock (m_Queue)
{
m_Queue.Enqueue(value);
Monitor.Pulse(m_Queue);
}
}
}
public class ParallelExcecuter
{
private readonly BlockingCollection<Task> _workItemHolder;
public ParallelExcecuter(int maxDegreeOfParallelism)
{
_workItemHolder = new BlockingCollection<Task>(maxDegreeOfParallelism);
}
public void Submit(Action action)
{
_workItemHolder.Add(Task.Run(action).ContinueWith(t =>
{
_workItemHolder.Take();
}));
}
public void WaitUntilWorkDone()
{
while (_workItemHolder.Count < 0)
{
Monitor.Wait(_workItemHolder);
}
}
}

catching exceptions from another thread

I have a method running in a seperate thread. The thread is created and started from a form in a windows application. If an exception is thrown from inside the thread, what is the best way to pass it back to the main application. Right now, I'm passing a reference to the main form into the thread, then invoking the method from the thread, and causing the method to be called by the main application thread. Is there a best practice way to do this because I'm not comfortable with how I'm doing it now.
Example of my form:
public class frmMyForm : System.Windows.Forms.Form
{
/// <summary>
/// Create a thread
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnTest_Click(object sender, EventArgs e)
{
try
{
//Create and start the thread
ThreadExample pThreadExample = new ThreadExample(this);
pThreadExample.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Application.ProductName);
}
}
/// <summary>
/// Called from inside the thread
/// </summary>
/// <param name="ex"></param>
public void HandleError(Exception ex)
{
//Invoke a method in the GUI's main thread
this.Invoke(new ThreadExample.delThreadSafeTriggerScript(HandleError), new Object[] { ex });
}
private void __HandleError(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Example of my thread class:
public class ThreadExample
{
public delegate void delThreadSafeHandleException(System.Exception ex);
private Thread thExample_m;
frmMyForm pForm_m;
private frmMyForm Form
{
get
{
return pForm_m;
}
}
public ThreadExample(frmMyForm pForm)
{
pForm_m = pForm;
thExample_m = new Thread(new ThreadStart(Main));
thExample_m.Name = "Example Thread";
}
public void Start()
{
thExample_m.Start();
}
private void Main()
{
try
{
throw new Exception("Test");
}
catch (Exception ex)
{
Form.HandleException(ex);
}
}
}
So you're using Invoke to marshall back to the UI thread, by the looks of it - which is exactly what you need to do. I'd personally use an Action<Exception> for simplicity's sake, and possibly BeginInvoke instead of Invoke, but basically you're doing the right thing.
Use the BackgroundWorker class in the .NET framework instead. It is the best practice for performing UI work on a different thread.
Probably a better way would be to pass a delegate into the thread instead of a reference to the form itself.
Throwing exceptions between threads is not easy and probably not desired. instead you can pass the exception using a shared data structure or variable and use waitHandle to wait on the 1st thread.
I totally agree with Dror. In a formal way we can call this structure as FaultContract. Fundamentally when an exception has happened in another thread, the client thread can hardly do any thing at that moment except that to collect that information and act accordingly in it's own theread. If the thereads are in different AppPool then there is an extra complexity of Serialization (that can be a seperate topic altogether).

Categories

Resources