2015-11-12 4 views
3

Я не могу придумать способ сделать что-то вроде этого: у меня есть взаимодействие с C# с другим устройством с использованием последовательного порта, и это устройство может иногда иметь прерывания, которые блокируют выполнение на себе , но после того, как она была исправлена, операция продолжается до тех пор, пока она не закончится.Возвращаемые данные при выполнении метода блокировки

Например, подумайте о принтере, на принтере начнет печатать 100 заданий, но в принтере 70 документов, поэтому принтер печатает 70 страниц, а затем предупреждает пользователя через ПК, чтобы положить больше документов в лоток. после того как пользователь помещает бумагу в нее, печать продолжается и после окончания печати принтер отправляет результат на ПК.

Это ситуация, но происходит быстрее, чем принтер. Как я могу закодировать что-то вроде этого? Например:

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

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

Если у вас есть только этот SendPrinterDocument() метод, и он блокирует выполнение приложения, как это в библиотеке DLL, как бы вы вызвать ShowPaperOutError() сообщение?

FYI У меня есть доступ ко всем кодам, программному обеспечению ПК (C#), DLL (C#) и устройству (C) и их компиляция.

+0

Как вы называете свой 'ShowPaperOutError'? Через событие? –

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

Edit, на основе комментариев:

Идея выше быстро разрывается, если ваш привод Все функциональные возможности достаточно быстрены, чтобы завершить работу до того, как вы на самом деле назначили обработчики событий. В этом случае вам, вероятно, понадобится второй параметр для вашей функции, который предоставляет некоторые «обратные вызовы», которые вызываются при возникновении соответствующих событий. Вы можете использовать такую ​​же настройку:

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

Кажется разумным для меня, но ваш код имеет проблему. Что делать, если печать заканчивается до 'PrintingFinished'? Я бы поставил этот материал на метод печати, прежде чем он на самом деле распечатает. –

+0

Да, я думаю, вы, вероятно, правы - вот почему это скорее «идеи», а не фактическая реализация. Для долговременной задачи (например, для печати) этот способ, как правило, работает нормально, для чего-то более быстрого, нет смысла назначать обработчики событий при ответе. Это вызов, основанный на функциональности OP * на самом деле * – Jamiec

+0

Да, эта идея обработчика событий кажется разумной и практичной для передачи прерываний из dll во внешний мир. Я сделаю это. Спасибо. –