Могу ли я использовать реактивные расширения для очереди вызовов в службу Windows? - PullRequest
2 голосов
/ 07 марта 2012

У меня есть оконная служба, которая вызывает не поточно-безопасный API (ghostscript) для преобразования pdf в изображения, поэтому мне нужно убедиться, что вызов метода вызывается по одному, но ставить в очередь все вызовы, которые могут поступать из различных экземпляры приложения.

приложение -> служба windows -> ghostscript

Ответы [ 2 ]

3 голосов
/ 10 марта 2012

Вот, пожалуйста:

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());
1 голос
/ 09 марта 2012

Rx - это немного излишне для этой работы.Рассмотрите TPL , если у вас есть сложные потребности в очередях / ожидании / пакетировании.

Если ваши требования просты, вы можете пойти на простые Task.Start(...), Task.ContinueWith(...), чтобы создать потокобезопасныйочередь на обработку.

Это может быть просто:

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());
    }
}

Самый простой способ проверить это - использовать TPL, поэтому:

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)
);

Результаты:

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
...