Skip to content

XPrinter - Issues with status callbacks and the library not letting go of the printer on Dispose #295

@TheGreenAirplane

Description

@TheGreenAirplane

Hello,

my company operates a number of kiosk PCs with XPrinter thermal printers for printing tickets. We're using your library to control the printers.
When I implemented this over a year ago, I used the StatusChanged event to get the printer status:

_printer = new FilePrinter(filePath: _port);
_printer.StatusChanged += StatusChanged;
_printer?.Write(e.Initialize());
_printer?.Write(e.Enable());
_printer.Write(e.EnableAutomaticStatusBack());

We use this mainly to find out if the printer is out of paper - in which case the app stops trying to print any more tickets and notifies the assigned employee to refill the paper.

This worked great. I knew I could rely on this, because throughout all my testing the printer was reliably sending status updates every time something changed. And sometimes even when nothing changed - I had to filter out those irrelevant updates. Seriously, I would look sideways at the printer and it would send a status update.

Fast forward to today, we received a new batch of kiosks, presumably with new printers. Suddenly we've run into an issue: clients report that the kiosk is no longer reporting when the printer is out of paper, and when the paper is refilled, the printer will print all the tickets that were not printed due to lack of paper. It seems our app lost the ability to tell when the printer is out of paper, and just kept sending it data to print, which the printer stored in its buffer.

I went back and troubleshooted the app, and found out the new printers are sending status updates very sporadically. Sometimes the update comes right after initialization, sometimes it doesn't. I can also open the cover, remove the paper, and close the cover while the app is listening, and nary an update comes.

I've talked to the kiosk vendor's tech support, they suggested I query the printer directly. Your library doesn't support querying the printer directly, and I know this is by design. Writing the query to the printer via your lib doesn't work either, because the Write method is a void, and there's no Read method, so I have no way of getting a response.

So I've implemented an approach that doesn't involve your library:

int fd = Syscall.open(printerPath, OpenFlags.O_RDWR | OpenFlags.O_NONBLOCK);
...
var writeResult = Syscall.write(fd, (IntPtr)writePtr, (ulong)queryCommand.Length);
...
var readResult = Syscall.read(fd, (IntPtr)readPtr, (ulong)response.Length); // read result has the current status of the printer (either normal, out of paper or cover open)

This works reliably, but it only works if I haven't used your lib for printing yet. Once I've initialized the printer, it holds a lock on the port, and doesn't relinquish it even if I dispose it:

_printer.StatusChanged -= StatusChanged; 
_printer.Dispose();
_printer = null;
GC.Collect();
GC.WaitForPendingFinalizers();

This doesn't help. I'm unable to successfully call Syscall.open after this. The only thing that helps is restarting my app.

Is there a way I could either
a) use your library to actively query the printer after all,
or
b) have the library relinquish the printer resource so that I can query it independently?

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions