1

I have a Winforms application where I am trying to print a pdf document which has multiple layers on it. But the problem is, This all operation are running on UI thread and it is hanging the UI(not responding) for long time. I know, this is happening because of UI thread is blocked so, I have tried to make this operation asynchronous by the help of powerful async/await keyword but still my long running method is not being asynchronous. It is not coming forward from the await tasks and still opearation is taking the same time as like synchronous operation.

What I tried:

Please see below:

/// <summary> /// Show Print Dialog /// </summary> private void ShowPrintDialog() { // Initialize print dialog System.Windows.Controls.PrintDialog prtDialog = new System.Windows.Controls.PrintDialog(); prtDialog.PageRangeSelection = PageRangeSelection.AllPages; prtDialog.UserPageRangeEnabled = false; _printOptions.PrintQueue = null; _printOptions.PrintTicket = null; Enabled = false; // if there is a default printer then set it string defaulPrinter = prtDialog.PrintQueue == null ? string.Empty : prtDialog.PrintQueue.FullName; // Display the dialog. This returns true if the user selects the Print button. if (prtDialog.ShowDialog() == true) { _printOptions.PrintQueue = prtDialog.PrintQueue; _printOptions.PrintTicket = prtDialog.PrintTicket; _printOptions.UseDefaultPrinter = (defaulPrinter == prtDialog.PrintQueue.FullName); } // Re-enable the form Enabled = true; } /// <summary> /// Event raised when user clicks Print /// </summary> /// <param name="sender">Source of the event</param> /// <param name="e">Event specific arguments</param> private void cmdOk_Click(object sender, EventArgs e) { ShowPrintDialog(); if (_printOptions.PrintTicket != null) { //Set search Options _print.ExportDataItem = true; _print.FileName = SearchTemplateName; //shows progress bar form. using (frmPrintSearchResultsProgress frmProgress = new frmPrintSearchResultsProgress(_print, this, _printOptions)) { frmProgress.ShowDialog(this); } if (_print.ExportDataItem && !_print.DataItemExported && !_print.CancelExport) { MessageBox.Show("No Document printed."); } } //Store selected options for current user SaveOptions(); if (!SkipExport) Close(); } /// <summary> /// Event raised when progress form is shown. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void frmExportSearchResultsProgress_Shown(object sender, EventArgs e) { try { Application.DoEvents(); dispatcher = Dispatcher.CurrentDispatcher; // record export/print job start time _startedUtc = DateTime.UtcNow; _print.WritingToPdfIndicator = lblWritingPdfFile; lblProgress.Text = Properties.Resources.PrintSearchResults; await dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(DoDataItemPrint)); } } /// <summary> /// Prints the selected data items. /// </summary> private void DoDataItemPrint() { // LONG RUNNING OPERATIONS.. // THIS OPERATION IS BLOCKING THE UI. } 

So, as per mentioned in above code when I opened the PringDialogForm then it is opening a Progress Bar form to see the progress of printing the document and from here frmExportSearchResultsProgress_Shown() event is fired and inside it, I am calling the DoDataItemPrint() method which is time consuming. So, I tried to make frmExportSearchResultsProgress_Shown event as async/await but still operation is taking the same time as previous.

Can anyone please suggest me where I am doing wrong?

2
  • All your code runs on the UI thread. There's nothing asynchronous Commented Sep 29, 2021 at 9:53
  • Please remove the Application.DoEvents(). It is evil. It is only in the framework for compatibility with VB6 from 2001. It can cause re-entrancy issues and even lock up your UI. You should remove it immediately. Commented Sep 29, 2021 at 22:07

1 Answer 1

6
  • your frmExportSearchResultsProgress_Shown method starts on the UI thread
  • it then dispatches DoDataItemPrint to the ... same UI thread
  • it schedules a continuation (via await) so that when that incomplete thing happens, we get back into frmExportSearchResultsProgress_Shown, and since there's probably a sync-context in play here, the sync-context capture (implicit in await) would push us to ... the UI thread

As you can see: everything is happening on the UI thread.

If you want to not block the UI, you need to get off the UI thread. That could be as simple as using Task.Run to invoke DoDataItemPrint, but without knowing what that code contains, it is impossible to know whether you're using thread-bound controls to do the printing. If you are... it will be hard to get away from that.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.