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 のおかげで、これはよくわかりました。