执行阻塞方法时返回数据

时间:2015-11-12 12:46:01

标签: c# multithreading interrupt blocking

我想不出一种方法可以做这样的事情:我有一个C#应用程序使用串口连接另一台设备,这个设备有时会有中断,它会阻止自身的执行,但一旦有了修复了操作一直持续到完成为止。

例如,想想一台打印机,打印机上开始打印100页作业,但打印机内部有70张纸,因此打印机打印70页,然后通过PC警告用户将更多纸张放入纸盘。用户将纸张放入其中后,打印继续,打印输出完成后,打印机将结果发送到PC。

这种情况但发生的速度比打印机快。我该如何编写这样的代码?例如:

private void StartPrinting()
{    
    boolean bIsPrinted = SendPrinterDocument("p100.pdf");
}

private void ShowPaperOutError()
{
    MessageBox.Show("Paper is out. Please load some papers");
}

如果你只有这个SendPrinterDocument()方法,它会阻止应用程序的执行,就像它在DLL库中一样,你会如何触发ShowPaperOutError()消息?

仅供参考,我可以访问所有代码,PC软件(C#),DLL(C#)和设备(C),并可以编译它们。

1 个答案:

答案 0 :(得分:4)

您可以通过让SendPrinterDocument返回一个引发适当事件的对象来实现这一点,并且可能会使用适当的方法来执行您需要的操作。

我将使用(半)伪代码,因为我无法看到您说您可以访问并且可以更改的所有代码 - 我假设您将能够实现此想法。

如果SendPrinterDocument立即返回实现此示例界面的对象:

public interface ISendPrinterDocumentResponse
{
    event EventHandler PrintingFinished;
    event EventHandler<PrintingInterruptedEventArgs> PrintingInterrupted;
    void Retry();
}

public class PrintingInterruptedEventArgs: EventArgs
{
     public string Reason { get;set; }
}

您可以使用它,例如:

var response = SendPrinterDocument("p100.pdf");
response.PrintingFinished = (s,ea) => MessageBox.Show("Finished");
response.PrintingInterrupted = (s,ea) => {
    MessageBox.Show("Printing stopped, hit ok to retry (reason:" + ea.Reason + ")");
    response.Retry();
};

根据评论进行修改:

如果您的实际功能足够快以至于在实际分配事件处理程序之前完成,上面的想法会很快崩溃,在这种情况下,您可能需要为您的函数提供第二个参数,这提供了一些“回调”在相关事件发生时被调用。您可以使用相同类型的设置:

public void SendPrinterDocument(string documentName, ISendPrinterEvents events);
{
     // when interrupted
     if(events.PrintingInterrupted != null)
     {
           events.PrintingInterrupted(this, new PrintingInterruptedEventArgs{Reason = "Out of paper"});
     }
}