Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9318

Windows 10 & .NET Framework の環境で印刷するとメモリリークする

$
0
0

背景

Windows 7 の頃には問題なかった処理が Windows 10 に変更するとメモリリークするようになったので調べてみた。

再現コード

varserver=newLocalPrintServer();varqueue=server.GetPrintQueue(this.SelectedPrinter.Value);varwriter=PrintQueue.CreateXpsDocumentWriter(queue);if(!String.IsNullOrWhiteSpace(this.SelectedFilePath.Value)){writer.Write(this.SelectedFilePath.Value);}

解説

Windows 7 の頃はこれで問題なかったのだが、 Windows 10 では GetPrintQueue() で取得した PrintQueue がメモリリークすることがある。

具体的には、 XpsDocumentWriter.Write() を実行すると、 Windows 10 では COM Surrogate (dllhost.exe) に処理を委譲するようになっており、印刷が終わっても PrintQueue が破棄されるまでメモリが解放されないようだ。

プリンタドライバを古いものに替えると起きなくなったので、ドライバの不具合を疑いメーカーに問い合わせした所、 PrintTicket に対応したドライバを使用すると起きるらしい。
dllhost.exe は OS のモジュールなのでメーカー側ではどうしようもできないようだ。

解決方法

印刷が終わったら PrintQueue を Dispose すればメモリが解放される。

varserver=newLocalPrintServer();using(varqueue=server.GetPrintQueue(this.SelectedPrinter.Value)){varwriter=PrintQueue.CreateXpsDocumentWriter(queue);if(!String.IsNullOrWhiteSpace(this.SelectedFilePath.Value)){writer.Write(this.SelectedFilePath.Value);}}

感想

本来、これが行儀のいい書き方なので、困っている人はあまりいないかもしれないが、 Visual Studio で印刷すると同様のリークが起きたりするので、 Microsoft 内でも想定外なバグなのかもしれない。
サンプルのコードなんかを単純にコピペしてる人は困っているかもしれない。

しかし、自分で new したものを Dispose するのは忘れないが、 GetPrintQueue() 内で新規にインスタンスが作成されていると思わないし、フレームワークが返したオブジェクトを勝手に Dispose してもいいのかとか色々考えてしまうので、あまり良い実装でないように思う。

因みにこのリークは .Net Core では起こりません。

サンプルコードはこちら


Viewing all articles
Browse latest Browse all 9318

Latest Images

Trending Articles