1

別のアプリケーション (この場合はメモ帳) を開始するフォームであるメイン スレッドがあり、メモ帳が閉じられるのを待つ BackgroundWorker を生成します。閉じると、BackgroundWorker は別の Form をユーザーに一番上に表示します。ユーザーがメイン スレッド ダイアログのいくつかのボタンをクリックできるように、このフォームは非モーダルである必要があります。問題は、このフォーム (BackgroundWorker の Form2) が TopMost ではなく、true に設定していることです。F5 キーを押すと機能しますが、ClickOnce アプリケーションとしてサーバーに公開すると、form2 は最上位ではなくなります。Form2.Topmost = true、BringToFront、Activate、"MakeTopMost"フォームを強制的に前面に出す強力な方法は何ですか? ....何も機能していないようです。

メイン フォームのハンドルを取得して、それを form2 の親として使用しようとしましたが、「InvalidOperationException: クロススレッド操作が無効です: コントロール 'Form2' がスレッド以外のスレッドからアクセスされました。に作成されました。」

コード スニペットを次に示します。

public partial class Form1 : Form
{
    System.Diagnostics.Process p = new System.Diagnostics.Process();
    private BackgroundWorker endApplicationBackgroundWorker= new BackgroundWorker();

    public Form1(string[] args)
    {
        endApplicationBackgroundWorker.DoWork += new DoWorkEventHandler(endApplicationBackgroundWorker_DoWork);

        p.StartInfo.FileName = "notepad";
        p.Start();

        endApplicationBackgroundWorker.RunWorkerAsync();

        //Quit here so we can accept user inputs (button pushes ..)
    }

    private void endApplicationBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        p.WaitForExit();

        Form2 form2 = new Form2();
        form2.TopMost = true;

        System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcessesByName(form1ProcessName);
        if (procs.Length != 0)
        {
            IntPtr hwnd = procs[0].MainWindowHandle;
            if (form2.ShowDialog(new WindowWrapper(hwnd)) == DialogResult.OK)
            {
                // process stuff
            }
        }

        this.Close();
    }
}

他のアイデアはありますか?または、誰かが上記のコードを修正できますか? 私はこの問題に何週間も取り組んでいて、慌てています。

ありがとう!

4

2 に答える 2

1

プロシージャDoWorkを呼び出した後にBackgroundWorkerのメソッドで行う作業は、UIスレッドでは実行されませんが、コードはバックグラウンドでフォームを作成しています。RunWorkerAsync

フォームはUI要素であるため、これは機能しません。

private void endApplicationBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
  Form2 form2 = new Form2();
  form2.TopMost = true;
  // etc..
  if (form2.ShowDialog(new WindowWrapper(hwnd)) == DialogResult.OK)
  {
    // process stuff
  }
}

コメントから、RunWorkerCompletedイベントに登録して2番目のフォームを表示する必要があります。Closeまた、呼び出しなしでForm2を存続させようとしているため、メソッドを呼び出すこともできません。したがって、2番目のフォームShowDialogのイベントをサブスクライブしてForm_Closing()、メインフォームを閉じるタイミングも通知してください。

public Form1(string[] args)
{
  endApplicationBackgroundWorker.DoWork += 
    new DoWorkEventHandler(endApplicationBackgroundWorker_DoWork);
  endApplicationBackgroundWorker.RunWorkerCompleted += 
    new RunWorkerCompletedEventHandler(endApplicationBackgroundWorker_RunWorkerCompleted);

  p.StartInfo.FileName = "notepad";
  endApplicationBackgroundWorker.RunWorkerAsync();
}

private void endApplicationBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
  p.Start();
  p.WaitForExit();
}

private void endApplicationBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  Form2 form2 = new Form2();
  form2.TopMost = true;
  form2.FormClosing += new FormClosingEventHandler(form2_FormClosing);    
  form2.Show(this);
}

private void form2_FormClosing(object sender, FormClosingEventArgs e)
{
  this.BeginInvoke(new MethodInvoker(delegate { this.Close(); }));
}
于 2012-03-27T21:12:33.330 に答える