1

ここと MSDN のすべての投稿を読んだと思いますが、ほとんどの記事や投稿が私がやろうとしていることをカバーしていないように見えるので、私は特別なケースだと思います。

Excel シートを調べて、レコードを取り出して渡し、別のファイル タイプに変換できるようにしています。私はスレッドを使用しようとしているので、UI を拘束せず、フォームにあるプログレス バーを更新する場合を除いて、すべて問題ありません。以下は、フォームを更新する必要があるクラスです。

public class ExcelItem : Form1
{
    private string inFile { get; set; }

    public ExcelItem(string file)
    {
        inFile = file;
    }

    public string getExcelData()
    {
        string result = "";
        int numRec = 0;
        int recCount = 0;
        Excel.Application xlApplication;
        Excel.Workbook xlWorkbook;
        Excel.Worksheet xlWorksheet;
        Excel.Range xlRange;

        xlApplication = new Excel.Application();
        xlWorkbook = xlApplication.Workbooks.Open(File, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
        xlWorksheet = (Excel.Worksheet)xlWorkbook.Worksheets.get_Item(2);
        xlRange = xlWorksheet.UsedRange;

        int rCnt = xlRange.Rows.Count;
        int cCnt = xlRange.Columns.Count;

        //for (int k = 1; k <= xlWorkbook.Worksheets.Count; k++)
        //    MessageBox.Show("Found worksheet " + k);

        // get the number of records in tne sheet and use numRec to set progress bar max
        for (int i = 1; i <= xlRange.Rows.Count; i++)
        {
            for (int j = 1; j <= xlRange.Columns.Count; j++)
            {
                if ((((Excel.Range)xlWorksheet.Cells[i, j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() == "Date of Birth"))
                {
                    numRec++;
                    //code for updating progress bar max would go here
                }
            }
        }

        // iterate through records in sheet, use recCount to set progress bar value and return records
        for (int i = 1; i <= xlRange.Rows.Count; i++)
        {
            for (int j = 1; j <= xlRange.Columns.Count; j++)
            {
                if ((((Excel.Range)xlWorksheet.Cells[i, j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() == "Date of Birth"))
                {
                    result += Environment.NewLine;
                    recCount++;
                    // code for updating progress bar value would go here
                }

                if ((((Excel.Range)xlWorksheet.Cells[i,j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() != ":"))
                {
                    result += (string)((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() + Environment.NewLine;
                }
            }
        }
        return result;
    }
}

}

レコードを返すことは問題ではありません。プログレス バーなどを更新することだけが今の頭痛の種です。これまでのところ、デリゲート、backgroundworker、BeginInvoker、およびスレッドを試しましたが、何も機能していないようです。助けてくれてありがとう。

4

2 に答える 2

0

含める必要がある System.Runtime.Remoting.Messaging にある AsyncCallBack を使用して、これにアプローチする別の方法を見つけました。以下は実際に私がやったことです:

AsyncCallBack メソッド (pbvalue はプライベート グローバル変数です):

public void setPg1InAnotherThread(Int32 val)
    {
        new Func<Int32>(setPbValue).BeginInvoke(new AsyncCallback(setPbValueCallback), null);
    }

    private Int32 setPbValue()
    {
        Int32 result = recCount;
        return result;
    }

    private void setPbValueCallback(IAsyncResult ar)
    {
        AsyncResult result = (AsyncResult)ar;
        Func<Int32> del = (Func<Int32>)result.AsyncDelegate;
        try
        {
            Int32 pbValue = del.EndInvoke(ar);
            if (pbValue != 0)
            {
                Form1 frm1 = (Form1)findOpenForm(typeof(Form1));
                if (frm1 != null)
                {
                    frm1.setPbValue(pbValue);
                }
            }
        }
        catch { }
    }

残っている唯一のことは、ファイル ハンドラーまたはデリゲートを介して行うことができなかったメイン フォームへの参照を取得することです。

private static Form findOpenForm(Type typ)
    {
        for (int i = 0; i < Application.OpenForms.Count; i++)
        {
            if (!Application.OpenForms[i].IsDisposed && (Application.OpenForms[i].GetType() == typ))
            {
                return Application.OpenForms[i];
            }
        }
        return null;
    }

これらのメソッドを配置したら、必要な値を指定して setPg1InAnotherThread() を呼び出すだけです。また、おそらく戻って Int32 を Int16 にリファクタリングします。これは推奨される方法ではなく、可能な場合は BackGroundWorker または通常のデリゲート メソッドを使用する必要がありますが、私の状況では機能しています。

于 2013-08-04T00:23:02.290 に答える