如何异步等待来自拦截打印机输出的外部应用程序的响应

时间:2012-02-07 16:11:03

标签: c# multithreading wcf redmon

我设计了一个由3个独立应用程序组成的系统:

  1. 网络应用程序
  2. WCF服务应用程序接收来自Web应用程序的请求,执行相应的操作并使用SendKeys类SendKeys.SendWait("^p");打印结果(这会发送一个Ctrl + P命令,在屏幕上显示最新内容)。
  3. 通过Console.In截取打印机输出(通过redmon的虚拟打印机)的控制台应用程序(如建议here
  4. WCF服务应用程序和Web应用程序可以轻松进行通信,但服务应用程序和控制台应用程序之间没有直接通信。控制台应用程序仅在有打印机作业且WCF应用程序不知道打印作业的结果时启动。

    有没有办法让WCF服务应用程序接收来自打印作业的反馈(无论是否正常),因此它可以将适当的响应发送回Web应用程序,而不会每秒执行Thread.Sleep()直到打印机应用程序完成打印并将结果保存在文件或数据库中?

    有没有办法可以暂停WCF服务应用程序中的线程,并在打印过程完成后从打印机控制台应用程序恢复它(同时发回信息)?

    编辑:

    我设法找到Richard Blewett的建议解决方案。该解决方案将使WCF服务应用程序等待,直到打印作业完成,但这将导致WCF应用程序被限制为一次只创建一个打印作业。

    我使用WCF应用程序中的某个键创建一个EventWaitHandle,如下所示:

    EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.ManualReset, "unique-key");
    WaitHandle.WaitAny(new WaitHandle[] { ewh });
    

    我可以像这样从控制台应用程序返回线程:

    EventWaitHandle ewh = EventWaitHandle.OpenExisting("unique-key");
    ewh.Set();
    

    使用Richard的解决方案情况并非如此,可以同时进行多个WCF服务调用。

1 个答案:

答案 0 :(得分:1)

假设打印作业有唯一标识符,则控制台应用程序可以调用WCF服务来说明打印作业已完成正常或失败。

WCF服务要么必须阻塞,直到完成调用进来(等待说一个ManualResetEventSlim),否则你必须将服务写为async service,这样请求线程就可以返回到池中了打印作业正在进行中。

您需要打印作业的唯一标识符的原因是您必须在服务中将数据结构映射到事件的唯一ID,以便在作业完成时发出正确的等待请求

当WCF服务创建一个打印作业时,它会将一个条目放入一个ConcurrentDictionary映射printJobId到一个非信号的ManualResetEventSlim(每个打印作业一个)。然后它等待事件发出信号。

现在,当打印作业完成时,控制台应用程序依次调用WCF服务传递其printJobId。此操作对字典进行操作,抓取事件并发出信号。知道打印作业已完成,原始调用现在醒来。

打印作业的状态也可以通过这个字典数据结构传递,所以你会有像

这样的东西
class PrintJob
{
    public PrintJob()
    { 
        Event = new ManualResetEventSlim();
    }

    public ManualResetEventSlim Event {get; private set;}

    public int Status{ get; set;}
}

并且字典会将printJobId映射到每个打印作业的其中一个。调用操作的控制台应用程序会将状态设置为打印作业的结果