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

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 9747

Trending Articles