Unless you created a transaction before call sp_getapplock, it was released at the end of implicit transaction. If it was part of the select query, it was released when the select finished. If you did it in its own sql statement, it released at the end of the statement.
If the lock is part of the datareader sql (it should be) than it release should be part of the batch also.
You get an error calling before reader completes, because a connection allows only one active query.