Reputation: 4747
I have a window service that is calling a non-thread safe api (ghostscript) to convert pdf's to images so I need to ensure the method call is called one at a time but queue all the calls which can be coming from various app instances.
app -> windows service -> ghostscript
Upvotes: 2
Views: 1119
Reputation: 12667
Rx is a bit of overkill for the job. Consider TPL if you have complex queuing/wait/batching needs.
If your requirements are simple, you can go for the simple Task.Start(...)
, Task.ContinueWith(...)
to create a thread-safe processing queue of sorts.
It could be as simple as:
public class TaskQueue
{
protected Task Pending;
public bool Ready { get { return Pending == null || Pending.IsCompleted || Pending.IsCanceled || Pending.IsFaulted; } }
public Task Enqueue(Action work)
{
lock (this)
return Pending = Ready ? Task.Factory.StartNew(work) : Pending.ContinueWith(_ => work());
}
}
The easiest way to test this is to use TPL, so:
var tasks = new TaskQueue();
Func<int, Action> queue = i => () => tasks.Enqueue(
() => { Thread.Sleep(1000); Console.WriteLine("{0}: {1}", DateTime.Now, i); });
Parallel.Invoke
(
queue(1),
queue(2),
queue(3),
queue(4)
);
Results:
3/10/2012 5:59:02 PM: 1
3/10/2012 5:59:03 PM: 2
3/10/2012 5:59:04 PM: 3
3/10/2012 5:59:05 PM: 4
Upvotes: 1
Reputation: 74654
Here you go:
var eventLoop = new EventLoopScheduler();
IObservable<Unit> QueueAnItem(string input)
{
return Observable.Start(() => CallGhostScriptAndWaitForItToFinish(input), eventLoop);
}
QueueAnItem("Foo").Subscribe(
x => Console.WriteLine("It Finished!"),
ex => Console.WriteLine("Something Bad Happened: {0}", ex.ToString());
Upvotes: 3