1

2時間の調査の後、私はまだ問題の解決策を見つけることができませんでした.

私が行うタスクは、BackGroundWorker スレッドでいくつかのファイルを処理することです。ただし、ユーザーが SaveFile の場所を選択できるように ShowDialog を使用する必要がある場合がありますが、STA/MTA エラーが発生します。

メインフォーム コード:

private void button2_Click(object sender, EventArgs e)
{
            button1.Enabled = false;
            ProcessReportWorker.RunWorkerAsync();
}

DoWork コード:

void ProcessReportWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int ReportCount = Reports.Count();
    foreach (string Report in Reports)
    {
            ProcessReport NewReport = new ProcessReport(Report);
        string result = NewReport.Start();
    }
} 

ProcessReport.Start() コード:

class ProcessReport
{
    public string Start() 
    {
        if(File.Exists(ResultPath))
        {
            SaveFileDialog SaveReport = new SaveFileDialog();
                    SaveReport.InitialDirectory = "c:\somepath";
                    SaveReport.CheckPathExists = true;
                    SaveReport.DefaultExt = ".xls";
                    SaveReport.OverwritePrompt = true;
                    SaveReport.ValidateNames = true;
                    if (SaveReport.ShowDialog() == DialogResult.OK)
                    {
                        ResultPath = SaveReport.FileName;
                        if (File.Exists(ResultPath)) File.Delete(ResultPath);
                    }
        }
    }
}

ご覧のとおり、場合によっては ShowDialog が必要です。これはデリゲートを使用して実行できると思いますが、デリゲートにはあまり詳しくありません。私は、BackgroundWorker での ShowDialog の呼び出しでJon の解決策を試しましたが、うまくいきませんでした。(多分私はデリゲートで何か間違ったことをしていますか?)

誰かがこれで私を助けてください。これに必要な場合は、デリゲートのコードを提供してください。ありがとう!

編集: PoweredByOrange によって提供されたソリューションが機能しました。ただし、小さな変更を加える必要がありました。

this.Invoke((MethodInvoker)delegate{....}); MainForm インスタンスを参照することを意図していますが、このコードは ProcessReport クラスに存在するため、機能しませんでした。したがって、ここでの「this」は ProcessReport クラスのインスタンスを参照していますが、機能するには GUI インスタンス (MainForm インスタンス) を参照する必要があります。

私の修正: MainForm のインスタンスを ProcessReport クラスに送信し、以下のように変更を加えました。

IN DoWork:

ProcessReport NewReport = new ProcessReport(Report, this); //CHANGE: Sending 'this'
//this sends reference of MainForm(GUI) to the ProcessReport Class

ProcessReport クラス:

 class ProcessReport
    {
        MainForm MainFormInstance;
        public ProcessReport(string report, MainForm x)
        {
            MainFormInstance = x;
        }
        public string Start() 
        {
            MainFormInstance.Invoke((MethodInvoker)delegate //changed this.Invoke to MainFormInstance.Invoke
                {
                   SaveFileDialog SaveReport = new SaveFileDialog();
                    SaveReport.InitialDirectory = "c:\somepath";
                    SaveReport.CheckPathExists = true;
                    SaveReport.DefaultExt = ".xls";
                    SaveReport.OverwritePrompt = true;
                    SaveReport.ValidateNames = true;
                    if (SaveReport.ShowDialog() == DialogResult.OK)
                    {
                        ResultPath = SaveReport.FileName;
                        if (File.Exists(ResultPath)) File.Delete(ResultPath);
                    }
                });
        }
    }

したがって、上記のことは最終的に機能しました。PoweredByOrange のおかげで、これはよくわかりました。

4

2 に答える 2

4

例外が発生する理由は、コントロールを所有するスレッドのみが変更/アクセスを許可されているためです。この場合、 はSaveFileDialogメイン スレッドに属していますが、Start()メソッドは別の (バックグラウンド) スレッドで実行されています。したがって、この場合のバックグラウンド スレッドは、メイン スレッドにその SaveFileDialog を開くように要求する必要があります。

public string Start() 
    {
        if(File.Exists(ResultPath))
        {
          this.Invoke((MethodInvoker)delegate
                {
                   SaveFileDialog SaveReport = new SaveFileDialog();
                    SaveReport.InitialDirectory = "c:\somepath";
                    SaveReport.CheckPathExists = true;
                    SaveReport.DefaultExt = ".xls";
                    SaveReport.OverwritePrompt = true;
                    SaveReport.ValidateNames = true;
                    if (SaveReport.ShowDialog() == DialogResult.OK)
                    {
                        ResultPath = SaveReport.FileName;
                        if (File.Exists(ResultPath)) File.Delete(ResultPath);
                    }
                });
        }
    }

より明確にするために、友人に彼の教科書の 1 つを渡してほしいと仮定します。友達の部屋に行って本を盗むことはできません。あなたができることは、友達に電話して ( invoke )、お願いを頼む ( delegate ) ことです。

于 2013-08-13T22:04:39.540 に答える