0

複数のスレッドを実行して、PDFファイルをフォルダーとそのサブディレクトリ内の画像に変換するプログラムがあります。そのフォルダーを繰り返し、すべてのpdfファイル名をリストに入れ、そのリストを使用して、作成した4つのスレッド間で作業を分割します。今ではすべてが完全に機能します。複数のスレッドが実行されており、同時にpdfファイルを指定した異なる場所に変換しています。

私はそれを正しい方法でやっているかどうか知りたいだけです。私がアクセスするほとんどすべてのWebサイトは、異なる方法でマルチスレッドを実行しますが、どれが最も効果的で、最終的には正しいものかわかりません。

うまくいくことをするのは良くありません、もしそれが間違っていたら、私は推測します...ただ将来私を手に入れるつもりです。

ここのコードを見て、実行中の複数のスレッドに関して変更する必要がある大幅に間違っているものがあるかどうかを確認していただければ幸いです。

static object LockInteger = new object();
static object LockIfCheck = new object();
static object LockInteger = new object();
static object LockIfCheck = new object();

private void button1_Click(object sender, EventArgs e)
{
    IterateThrough(txtboxdirectory.Text);
}

public void IterateThrough(string sourceDir)
{
    MulThread = new Thread(delegate()
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        int lowerbound = 0;
        int upperbound = (fileList.Count / 4);
        for (int i = lowerbound; i < upperbound; i++)
        {
            forFunction(exceptionFileList, fileList[i], compltetedFileList,sourceDir, dir1);
            stopWatch.Stop();
            lblFileExecutionTime.BeginInvoke(((Action)(() => lblFileExecutionTime.Text = "Execution Per File " + stopWatch.Elapsed.ToString())));
            stopWatch.Reset();
            stopWatch.Start();
        }
    });
    MulThread.Start();

    MulThread1 = new Thread(delegate()
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        int lowerbound = fileList.Count / 4;
        int upperbound = (fileList.Count / 4) * 2;
        for (int i = lowerbound; i < upperbound; i++)
        {
            forFunction(exceptionFileList, fileList[i], compltetedFileList, sourceDir, dir2);
            stopWatch.Stop();
            lblFileExecutionTime.BeginInvoke(((Action)(() => lblFileExecutionTime.Text = "Execution Per File " + stopWatch.Elapsed.ToString())));
            stopWatch.Reset();
            stopWatch.Start();
        }
    });
    MulThread1.Start();

    MulThread2 = new Thread(delegate()
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        int lowerbound = (fileList.Count / 4) * 2;
        int upperbound = (fileList.Count / 4) * 3;
        for (int i = lowerbound; i < upperbound; i++)
        {
            forFunction(exceptionFileList, fileList[i], compltetedFileList, sourceDir, dir3);
            stopWatch.Stop();
            lblFileExecutionTime.BeginInvoke(((Action)(() => lblFileExecutionTime.Text = "Execution Per File " + stopWatch.Elapsed.ToString())));
            stopWatch.Reset();
            stopWatch.Start();
        }
    });
    MulThread2.Start();

    MulThread3 = new Thread(delegate()
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        int lowerbound = (fileList.Count / 4) * 3;
        int upperbound;

        if (fileList.Count % 4 != 0)
        {
            upperbound = ((fileList.Count / 4) * 4) + (fileList.Count % 4) + 1;
        }
        else
        {
            upperbound = ((fileList.Count / 4) * 4) + (fileList.Count % 4);
        }

        for (int i = lowerbound; i < upperbound; i++)
        {
            forFunction(exceptionFileList, fileList[i], compltetedFileList, sourceDir, dir4);
            stopWatch.Stop();
            lblFileExecutionTime.BeginInvoke(((Action)(() => lblFileExecutionTime.Text = "Execution Per File " + stopWatch.Elapsed.ToString())));

            stopWatch.Reset();
            stopWatch.Start();
        }
    });
    MulThread3.Start();
}

次に、「forFunction」のメソッドのいくつかをロックします。

private int forFunction(String exceptionFileList, FileInfo z, String compltetedFileList, String sourceDir, String imagedirectory)
{
    //heres where it locked up because of this global variable
    lock (LockInteger)
    {
        atPDFNumber++;
    }

    int blankImage = 1;
    int pagesMissing = 0;

    //delete the images currently in the folder
    deleteCreatedImages(imagedirectory);

    //Get the amount of pages in the pdf
    int numberPDFPage = numberOfPagesPDF(z.FullName);

    //Convert the pdf to images on the users pc
    convertToImage(z.FullName, imagedirectory);

    //Check the images for blank pages
    blankImage = testPixels(imagedirectory, z.FullName);

    //Check if the conversion couldnt convert a page because of an error
    pagesMissing = numberPDFPage - numberOfFiles;

    //int pagesMissing = 0;

    //Cancel button is pressed
    if (toContinue == 0)
    {
        return 0;
    }

    lock (LockIfCheck)
    {
        //If there is a blank page, or if there is a missing page
        if (blankImage == 0 || pagesMissing > 0)
        {
            myholder = 1;
            exceptionFileList += "File Name: " + z.Name + "\r\n"
           + "File Path: " + z.FullName + "\r\n \r\n";

            String currentValue = exceptionFileList;
            txtboxProblemFiles.BeginInvoke(((Action)(() => txtboxProblemFiles.Text += currentValue.ToString())));

            String currentValue3 = z.FullName;
            txtboxProblemFiles.BeginInvoke(((Action)(() => listboxProblemFiles.Items.Add(currentValue3))));
        }
        else
        {
            compltetedFileList += "Scanning Completed of file: " + "\r\n"
            + "File Name: " + z.Name + "\r\n"
           + "File Path: " + sourceDir + "\r\n \r\n";
        }

        String currentValue1 = "File Name: " + z.Name + "\r\n";
        txtboxCheckedFiles.BeginInvoke(((Action)(() => txtboxCheckedFiles.Text += currentValue1)));
    }


    myWorkerClass();        

    return 1;
}

私はこのコードからの批判を構築することを受け入れます。

4

2 に答える 2

2

multitrheadingの推奨される方法は、ThreadPoolを使用することです。

ThreadPoolの利点は、スレッドの作成、ジョブの割り当てなどを管理し、リソースの使用量を減らしながらパフォーマンスを向上させることです。

MSDNのThreadPoolのサンプル:

using System;
using System.Threading;
public class Example {
    public static void Main() {

        // Queue the task.
        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));

        Thread.Sleep(1000);

        Console.WriteLine("Main thread exits.");
    }

    // This thread procedure performs the task. 
    static void ThreadProc(Object stateInfo) {

        // No state object was passed to QueueUserWorkItem, so  
        // stateInfo is null.
        Console.WriteLine("Hello from the thread pool.");
    }
}
于 2012-10-11T07:40:33.177 に答える
1

答えは状況次第だと思います。はい、スレッドを開始していますか。はい、共有データを保護しているように見えますか?どこにでもコピーして貼り付けたコードがあるように見えます。それを関数に抽象化し、上限と下限を引数にすることができます。これを減らして、Parallel.ForまたはParallel.ForEachを使用できると思います。最後に、GUIに関連するマルチスレッドの問題を完全に思い出せません。ここでGUIを使用しているようです。ただし、ラベルへの変更が他のスレッドではなくGUIスレッドによって行われることを確認する必要があります。

于 2012-10-11T07:42:59.657 に答える