Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit onderwerp wordt beschreven hoe u de afdruktaakverwerkingsthread start en stopt.
Overzicht
Als u wilt voorkomen dat afdrukactiviteiten het antwoord van de gebruikersinterface blokkeren, maakt u een afzonderlijke thread om de afdruktaak te verwerken. De thread die wordt gestart wanneer het programma wordt gestart, is de thread die de vensterberichten verwerkt die het gevolg zijn van gebruikersinteractie en is daarom de UI-thread. Het programma moet deze berichten zonder vertraging verwerken voordat de gebruikersinterface tijdig reageert op de invoer van de muis en het toetsenbord van de gebruiker. Om snel op deze berichten te kunnen reageren, is de hoeveelheid verwerking die tijdens één bericht kan worden uitgevoerd, beperkt. Wanneer een gebruikersaanvraag uitgebreide verwerking vereist, moet een andere thread die verwerking uitvoeren om verdere gebruikersinteractie door het programma te kunnen verwerken.
Voor het verwerken van gegevens in een afzonderlijke thread moet het programma de werking van de gebruikersinterfacethread en de verwerkingsthread coördineren. Wanneer de verwerkingsthread bijvoorbeeld de gegevens verwerkt, mag de hoofdthread die gegevens niet wijzigen. Een manier om dit te beheren, is via thread-veilige synchronisatieobjecten, zoals semaphores, gebeurtenissen en mutexes.
Tegelijkertijd moet enige gebruikersinteractie worden voorkomen terwijl de verwerkingsthread wordt uitgevoerd. In het voorbeeldprogramma worden de toepassingsgegevens beveiligd en wordt de interactie van de gebruiker beperkt doordat de verwerking van de afdruktaak wordt beheerd door het dialoogvenster modale voortgang. Een modaal dialoogvenster voorkomt dat de gebruiker interactie heeft met het hoofdvenster van het programma, waardoor de gebruiker de programmagegevens van de toepassing niet kan wijzigen terwijl de gegevens worden afgedrukt.
De enige actie die de gebruiker kan uitvoeren terwijl een afdruktaak wordt verwerkt, is door de afdruktaak te annuleren. Deze beperking wordt aan de gebruiker gesignaleerd door de vorm van de cursor. Wanneer de cursor boven de knop Annuleren bevindt, wordt er een pijlcursor weergegeven, die aangeeft dat de gebruiker op deze knop kan klikken. Wanneer de cursor zich op een ander deel van het venstergebied van het programma bevindt, wordt een wachtcursor weergegeven, die aangeeft dat het programma bezet is en niet kan reageren op gebruikersinvoer.
De procedure voor het creëren van de print-thread
We raden u aan deze functies op te nemen tijdens het verwerkingsproces.
afdrukverwerking is onderverdeeld in stappen
U kunt de afdrukverwerking verdelen in afzonderlijke verwerkingsstappen die u kunt onderbreken als de gebruiker op de knop Annuleren klikt. Dit is handig omdat afdrukverwerking processorintensieve bewerkingen kan bevatten. Het opsplitsen van deze verwerking in stappen kan voorkomen dat de afdrukverwerking andere threads of processen blokkeert of vertraagt. Als u de verwerking in logische stappen opsplitst, kunt u de afdrukverwerking op elk gewenst moment op een schone manier beëindigen, zodat het beëindigen van een afdruktaak voordat deze is voltooid, geen zwevende resources achterlaat.
Dit is een voorbeeldlijst met afdrukstappen.
HRESULT PrintStep_1_StartJob (PPRINTTHREADINFO threadInfo); HRESULT PrintStep_2_DoOnePackage (PPRINTTHREADINFO threadInfo); HRESULT PrintStep_3_DoOneDoc (PPRINTTHREADINFO threadInfo); HRESULT PrintStep_4_DoOnePage (PPRINTTHREADINFO threadInfo); HRESULT PrintStep_5_ClosePackage (PPRINTTHREADINFO threadInfo); HRESULT PrintStep_6_CloseJob (PPRINTTHREADINFO threadInfo);Controleren op een annuleer-event tussen stappen
Wanneer de gebruiker op de knop Annuleren klikt, geeft de gebruikersinterfacethread het annuleerevenement aan. De verwerkingsthread moet de gebeurtenis annuleren periodiek controleren om te weten wanneer een gebruiker op de knop Annuleren heeft geklikt. De WaitForSingleObject instructies voeren deze controle uit en ze geven ook andere programma's de kans om uit te voeren, zodat de verwerking van de afdruktaak geen andere threads of processen blokkeert of vertraagt.
In het volgende codevoorbeeld ziet u een van de tests om te zien of de gebeurtenis annuleren heeft plaatsgevonden.
waitStatus = WaitForSingleObject ( threadInfo->quitEvent, stepDelay); if (WAIT_OBJECT_0 == waitStatus) { hr = E_ABORT; }Statusupdates verzenden naar de thread van de gebruikersinterface
Tijdens elke stap voor het verwerken van afdrukken verzendt de afdrukverwerkingsthread updateberichten naar het dialoogvenster afdrukvoortgang, zodat de voortgangsbalk kan worden bijgewerkt. Het dialoogvenster Afdrukvoortgang wordt uitgevoerd in de UI-thread.
In het volgende codevoorbeeld wordt een van de aanroepen van het updatebericht geïllustreerd.
// Update print status PostMessage ( threadInfo->parentWindow, USER_PRINT_STATUS_UPDATE, 0L, 0L);
De afdrukthread starten
De thread voor afdrukverwerking blijft actief totdat de functie PrintThreadProc terugkeert. Met de volgende stappen wordt de afdrukthread gestart.
de gegevens- en gebruikersinterface-elementen voorbereiden voor afdrukken.
Voordat u de afdrukverwerkingsthread start, moet u de gegevenselementen initialiseren die de afdruktaak en de elementen van de gebruikersinterface beschrijven. Deze elementen bevatten de cursorstatus, zodat de wachtcursor correct wordt weergegeven. U moet ook de voortgangsbalk zo configureren dat deze overeenkomt met de grootte van de afdruktaak. Deze voorbereidingsstappen worden gedetailleerd beschreven in Procedure: Afdruktaakgegevens verzamelen van de gebruiker.
In het volgende codevoorbeeld ziet u hoe u de voortgangsbalk zo configureert dat deze overeenkomt met de grootte van de afdruktaak die de gebruiker heeft aangevraagd.
// Compute the number of steps in this job. stepCount = ((( // One copy of a document contains // one step for each page + // one step for the document ((threadInfo->documentContent)->pages + 1) * // Each copy of the document includes // two steps to open and close the document threadInfo->copies) + 2) * // Each job includes one step to start the job threadInfo->packages) + 1; // Send the total number of steps to the progress bar control. SendMessage ( dlgInfo->progressBarWindow, PBM_SETRANGE32, 0L, (stepCount));De afdrukverwerkingsthread starten.
Roep CreateThread- aan om de verwerkingsthread te starten.
In het volgende codevoorbeeld wordt de verwerkingsthread gestart.
// Start the printing thread threadInfo->printThreadHandle = CreateThread ( NULL, 0L, (LPTHREAD_START_ROUTINE)PrintThreadProc, (LPVOID)threadInfo, 0L, &threadInfo->printThreadId);Controleer of de afdrukverwerking is mislukt bij het starten.
CreateThread retourneert een handle naar de gemaakte thread als de thread succesvol is gemaakt. De functie PrintThreadProc die in de nieuwe thread is gestart, controleert enkele voorwaarden voordat de werkelijke verwerking van de afdruktaak wordt gestart. Als er fouten worden gedetecteerd in deze controles, kan PrintThreadProc worden beëindigd zonder afdruktaakgegevens te verwerken. De UI-thread kan controleren of de verwerkingsthread is gestart door te wachten op de thread-ingang voor een periode die langer is dan nodig is om de eerste tests uit te voeren, maar niet langer dan nodig is. Wanneer de thread wordt afgesloten, wordt de handle naar de thread als gesignaleerd beschouwd. De code controleert de status van de thread gedurende een korte periode nadat deze de verwerkingsthread heeft gestart. De functie WaitForSingleObject retourneert wanneer ofwel de time-out optreedt of het thread-handle wordt gesignaleerd. Als de functie WaitForSingleObject een WAIT_OBJECT_0 status retourneert, wordt de thread vroeg afgesloten en moet u het dialoogvenster afdrukvoortgang sluiten, zoals in het volgende codevoorbeeld wordt weergegeven.
// Make sure the printing thread started OK // by waiting to see if it is still running after // a short period of time. This time delay should be // long enough to know that it's running but shorter // than the shortest possible print job. waitStatus = WaitForSingleObject ( threadInfo->printThreadHandle, THREAD_START_WAIT); // If the object is signaled, that means that the // thread terminated before the timeout period elapsed. if (WAIT_OBJECT_0 == waitStatus) { // The thread exited, so post close messages. PostMessage (hDlg, USER_PRINT_CLOSING, 0L, (LPARAM)E_FAIL); PostMessage (hDlg, USER_PRINT_COMPLETE, 0L, (LPARAM)E_FAIL); }
De afdrukthread stoppen
Wanneer de gebruiker op de knop Annuleren in het dialoogvenster Afdrukvoortgang klikt, wordt de afdrukthread op de hoogte gesteld zodat de afdruktaak niet meer op een ordelijke manier kan worden verwerkt. Terwijl de Annuleren-knop en de afsluitgebeurtenis belangrijke aspecten van deze verwerking zijn, moet u de volledige verwerkingsvolgorde zodanig ontwerpen dat deze effectief kan worden onderbroken. Dit betekent dat de stappen in de reeks geen toegewezen resources mogen achterlaten die niet worden vrijgemaakt als een gebruiker de volgorde annuleert voordat deze is voltooid.
In het volgende codevoorbeeld wordt getoond hoe het voorbeeldprogramma de stopgebeurtenis controleert op voordat elke pagina in het document wordt geprint. Als het quitEvent- wordt gesignaleerd of er een fout is gedetecteerd, stopt de printverwerking.
// While no errors and the user hasn't clicked cancel...
while (((waitStatus = WaitForSingleObject (
threadInfo->quitEvent,
stepDelay)) == WAIT_TIMEOUT) &&
SUCCEEDED(hr))
{
// ...print one page
hr = PrintStep_4_DoOnePage (threadInfo);
// Update print status
PostMessage (
threadInfo->parentWindow,
USER_PRINT_STATUS_UPDATE,
0L,
0L);
if (threadInfo->currentPage < (threadInfo->documentContent)->pages)
{
// More pages, so continue to the next one
threadInfo->currentPage++;
}
else
{
// Last page printed so exit loop and close
break;
}
}