Themes for WebBrowser.Print ()

I am trying to create a GUI program that generates HTML invoices and sends them for printing.
It works for me. However, now I want to introduce threading.

I have a form with BackgroundWorker . The working column runs this code:

 #region BackGroundWorker private void bg_htmlGeneration_DoWork(object sender, DoWorkEventArgs e) { //SOME MORE CODE.. foreach (XElement ele in Lib.GetInvoiceElement(inv, ico.Supplier)) { PrintDocument(Lib.CreateHTMLFile()); } } #endregion public void PrintDocument(string fileName) { var th = new Thread(() => { WebBrowser webBrowserForPrinting = new WebBrowser(); webBrowserForPrinting.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(PrintDocumentHandler); webBrowserForPrinting.Url = new Uri(fileName); Application.Run(); }); th.SetApartmentState(ApartmentState.STA); th.Start(); } public void PrintDocumentHandler(object sender, WebBrowserDocumentCompletedEventArgs e) { ((WebBrowser)sender).Print(); ((WebBrowser)sender).Dispose(); Application.ExitThread(); } 

Everything goes fine. However, the WebBrowser object refuses to print. No errors (this is obvious), the program ends with nothing sent to the printer.
When I pick up the thread, the program runs again.

My knowledge of streaming is weak, and I teach myself quite a lot - therefore, apparently, I do not understand how the priority of threads is given.

Here How it should work:

  • The user selects the invoice on the main form, selects the print.
  • The background stream disappears and prints them while the user continues to work on the program.

Any ideas would be appreciated.

+4
source share
1 answer

The main problem with your WebBrowser code is incorrect.

WebBrowser supposed WebBrowser be used for an interactive web browser, during which the user does some things on the Internet. But in your case, you use WebBrowser only for printing after loading html. This is not true for two reasons:

  • Your code creates the entire Windows Forms control and does not use even half of its functionality.
  • Your code is trying to use the WinForms control in the background thread, which leads to unexpected behavior.

BackgroundWorker class that is supposed to be used for

Perform a long-running operation in the background (for example, database downloads and transactions).

Much more:

You must be careful not to manipulate user interface objects in the DoWork event DoWork . Instead, exchange the ProgressChanged and RunWorkerCompleted events with the user interface.

In the background thread, your code will not work because the WinForms control is a user-interface object .

For a write-only WebBrowser.Print method, it calls its own windows API, so you have no chance it will work in the background. From the disassembly code:

 this.AxIWebBrowser2.ExecWB(NativeMethods.OLECMDID.OLECMDID_PRINT, NativeMethods.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref obj, IntPtr.Zero); 

So my suggestion for your code is:

  • Remove using the WebBrowser class in the background. Use HttpWebRequest instead to download web content.
  • Choose a different method for printing downloaded content. Possible options:

PS: in the comments you said that you may need a PDF from your html. I did this using C # in two ways:


Some update here:

As we have async/await and TPL variants of laborious operations, I do not recommend you to use BackgroundWorker anymore.

+3
source

Source: https://habr.com/ru/post/1443042/


All Articles