4

HTMLの請求書を生成して印刷用に送信するGUIプログラムを作成しようとしています。
私はこれを機能させています。しかし、今はスレッディングを紹介したいと思います。

が付いたフォームがありBackgroundWorkerます。バックグラウンドワーカーは次のコードを実行します。

#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();
}

すべてがうまくいきます。ただし、WebBrowserオブジェクトは印刷を拒否します。エラーはありません(明らかです)。プログラムは、プリンターに何も送信されずに終了します。
スレッドを削除すると、プログラムは再び機能します。

私の糸脱毛の知識は弱く、私はほとんど自分自身を教えています-おそらく私は糸脱毛の優先順位がどのように設定されているかを誤解しています。

仕組みは次のとおりです。

  1. ユーザーはメインフォームで請求書を選択し、印刷することを選択します。
  2. ユーザーがプログラムを続行している間、バックグラウンドスレッドが消えて印刷されます。

任意のアイデアをいただければ幸いです。

4

1 に答える 1

3

コードの主な問題は、WebBrowser使用が間違っています。

WebBrowserインタラクティブなウェブブラウジングに使用されることになっており、その間にユーザーはインターネットでいくつかのことを行います。しかし、あなたの場合、htmlをダウンロードした後の印刷のためだけにWebBrowserを使用しています。これは2つの理由で間違っています:

  1. コードはWindowsフォームコントロール全体を作成し、その機能の半分も使用しません。
  2. コードはバックグラウンドスレッドでWinFormsコントロールを使用しようとしますが、これにより予期しない動作が発生します。

BackgroundWorkerに使用されることになっているクラス

バックグラウンドで時間のかかる操作(ダウンロードやデータベーストランザクションなど)を実行します。

はるかに:

イベントハンドラーでユーザーインターフェイスオブジェクトを操作しないように注意する必要があります。代わりに、およびイベントDoWorkを介してユーザーインターフェイスと通信します。ProgressChangedRunWorkerCompleted

WinFormsコントロールはであるため、コードはバックグラウンドスレッドで失敗しますuser-interface object

念のため、WebBrowser.PrintメソッドはネイティブWindows APIを呼び出すため、これがバックグラウンドで機能する可能性はありません。逆アセンブルコードから:

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

だから、あなたのコードに対する私の提案は次のとおりです:

  1. WebBrowserバックグラウンドでのクラスの使用を削除します。HttpWebRequest代わりに、Webコンテンツのダウンロードに使用してください。
  2. ダウンロードしたコンテンツを印刷する他の方法を選択してください。オプションは次のとおりです。

PS:コメントの中であなたはあなたがPDFあなたのhtmlからを必要とするかもしれないと言いました。私は2つの方法でC#によってこれを行いました:

  • wkhtmltopdfを使用したバッチ処理
  • Microsoft Officeアドインの使用:Microsoft SaveasPDFまたはXPS
    このアドインはサーバーにインストールする必要があります。その後、MSOfficeクラスを使用して出力をPDF形式で簡単に保存できます。

ここでいくつかの更新:

時間のかかる操作のためのオプションasync/awaitTPLオプションがあるので、このBackgroundWorkerクラスを使用することはもうお勧めしません。

于 2012-11-02T10:45:08.633 に答える