第15回 スレッドで処理する

複数のPDFファイルを一度に変換すると、変換中はUI動作が固まります。
それを防ぐため、変換処理をスレッド上で実行するように変更します。

今回はTaskを利用しました。
処理の開始中はドラッグアンドドロップを禁止し、新たな処理が開始されるのを防いでいます。

■Form1.cs
using System;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Pdf2Pdf
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();

			Label label1 = new Label();
			label1.Parent = this;
			label1.Dock = DockStyle.Fill;
			label1.TextAlign = ContentAlignment.MiddleCenter;
			label1.Text = "ここに\"小説家になろう\"縦書きPDFをドラッグアンドドロップしてください";

			label1.AllowDrop = true;

			label1.DragEnter += (sender, e) =>
			{
				if (e.Data.GetDataPresent(DataFormats.FileDrop))
				{
					e.Effect = DragDropEffects.Copy;
				}
			};

			label1.DragDrop += (sender, e) =>
			{
				if (e.Data.GetDataPresent(DataFormats.FileDrop))
				{
					string[] items = (string[])e.Data.GetData(DataFormats.FileDrop);


					//タスク(スレッド)で実行
					Task.Run(() =>
					{
						string strLabel = label1.Text;		//ラベル文字を処理中は退避

						Invoke((MethodInvoker)delegate
						{
							label1.AllowDrop = false;		//処理中は新たなドラッグアンドドロップを禁止する
							label1.Text = "変換処理を開始します。\n処理合計ファイル数:" + items.Length;
						});

						for (int i = 0; i < items.Length; i++)
						{
							string file = items[i];

							if (File.Exists(file) == false)
								continue;

							//「小説家になろう」縦書きPDFを読み込む
							PDFTextReader pr = new PDFTextReader();
							bool ret = pr.Read(file);

							string strTitle = "";

							//読み込んだ縦書きPDFに含まれる小説のタイトルを取得
							//(タイトルは最初のページの最初のstrText)
							foreach (PDFPage page in pr.Pages)
							{
								foreach (object obj in page.Items)
								{
									if (obj.GetType() != typeof(PDFText))
										continue;

									strTitle = (obj as PDFText).strText;
									if (strTitle != "")
										break;
								}
								if (strTitle != "")
									break;
							}

							//小説タイトルをファイル名にする
							// →ファイル名に使えない文字を除去
							{
								//ありがちな文字は決め打ちで全角に
								strTitle = strTitle.Replace('*', '*');
								strTitle = strTitle.Replace('\\', '¥');
								strTitle = strTitle.Replace(':', ':');
								strTitle = strTitle.Replace('<', '<');
								strTitle = strTitle.Replace('>', '>');
								strTitle = strTitle.Replace('?', '?');
								strTitle = strTitle.Replace('|', '|');

								char[] pcbInvalid = Path.GetInvalidFileNameChars();

								//使えない文字除去
								foreach (char c in pcbInvalid)
								{
									strTitle = strTitle.Replace(c.ToString(), "");
								}

								//タイトルがなくなったら、元々のPDFのファイル名に"_cnv"を付加
								if (strTitle == "")
									strTitle = Path.GetFileNameWithoutExtension(file + "_cnv");
							}

							string strNewFile = "";

							//書き出したいファイル名がすでに存在していたら、上書きしないように存在しないファイル名を生成
							while (true)
							{
								strNewFile = Path.GetDirectoryName(file) + "\\" + strTitle + ".pdf";
								if (File.Exists(strNewFile) == false)
									break;

								strTitle += "_" + DateTime.Now.Ticks;
							}

							//横書きPDFを書き出す
							PDFTextWriter pw = new PDFTextWriter();
							pw.ConvertPDFFile(strNewFile, pr);

							Invoke((MethodInvoker)delegate
							{
								label1.Text = "変換処理中です。\n残りファイル数:" + (items.Length - i - 1);
							});
						}

						Invoke((MethodInvoker)delegate
						{
							label1.AllowDrop = true;		//ドラッグアンドドロップ受付可能にする
							label1.Text = strLabel;			//ラベル文字を元に戻す
						});
					});

				}
			};

プロジェクトファイルをダウンロード


カテゴリー「PDFを処理する(C#)」 のエントリー