4

ユーザーに表示するデータを収集するのに長い時間がかかる WinForm ロード メソッドがあります。

このメソッドの実行中に、「Loading」という単語を含む大きなフォントのフォームを表示します。

ただし、このエラーが発生し、「読み込み中」進行状況フォームが閉じず、最終的にアプリケーション全体が終了することがあります。

ウィンドウ ハンドルの作成中にエラーが発生しました。System.Windows.Forms.NativeWindow.CreateHandle (CreateParams cp) で

load メソッドでコードを実行しているときに、進行状況/読み込みフォームを表示するより良い方法はありますか?

これは私のコードです:

//I launch a thread here so that way the Progress_form will display to the user
//while the Load method is still executing code.  I can not use .ShowDialog here
//or it will block.

//Progress_form displays the "Loading" form    
Thread t = new Thread(new ThreadStart(Progress_form));  

t.SetApartmentState(System.Threading.ApartmentState.STA);
t.IsBackground = true;
t.Start();

//This is where all the code is that gets the data from the database.  This could
//take upwards of 20+ seconds.

//Now I want to close the form because I am at the end of the Load Method                         

try
{
   //abort the Progress_form thread (close the form)
   t.Abort();
   //t.Interrupt();
}
catch (Exception)
{
}
4

3 に答える 3

10

ABackgroundWorkerは、UI スレッドをロックせずに実行時間の長い操作を実行する優れた方法です。

次のコードを使用して、BackgroundWorker を開始し、読み込みフォームを表示します。

// Configure a BackgroundWorker to perform your long running operation.
BackgroundWorker bg = new BackgroundWorker()
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);

// Start the worker.
bg.RunWorkerAsync();

// Display the loading form.
loadingForm = new loadingForm();
loadingForm.ShowDialog();

これにより、次のメソッドがバックグラウンド スレッドで実行されます。このスレッドから UI を操作することはできません。そうしようとすると、例外が発生します。

private void bg_DoWork(object sender, DoWorkEventArgs e)
{
    // Perform your long running operation here.
    // If you need to pass results on to the next
    // stage you can do so by assigning a value
    // to e.Result.
}

長時間実行される操作が完了すると、このメソッドが UI スレッドで呼び出されます。UI コントロールを安全に更新できるようになりました。あなたの例では、読み込みフォームを閉じたいと思うでしょう。

private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Retrieve the result pass from bg_DoWork() if any.
    // Note, you may need to cast it to the desired data type.
    object result = e.Result;

    // Close the loading form.
    loadingForm.Close();

    // Update any other UI controls that may need to be updated.
}
于 2013-04-02T18:19:45.310 に答える
2

これを .NET 4.0 で正常にテストしました。(WinForms) これは .NET 4.0 以降で機能し、プロセスの最後にフォームを閉じる必要があるほとんどのプロジェクトで再利用できる便利なコード スニペットになるはずです。

private void SomeFormObject_Click(object sender, EventArgs e)
{
    myWait = new YourProgressForm();//YourProgressForm is a WinForm Object
    myProcess = new Thread(doStuffOnThread);
    myProcess.Start();
    myWait.ShowDialog(this);
}

private void doStuffOnThread()
{
    try
    {
        //....
        //What ever process you want to do here ....
        //....

        if (myWait.InvokeRequired) {
            myWait.BeginInvoke( (MethodInvoker) delegate() { closeWaitForm(); }  );
        }
        else
        {
            myWait.Close();//Fault tolerance this code should never be executed
        }
    }
    catch(Exception ex) {
        string exc = ex.Message;//Fault tolerance this code should never be executed
    }
}

private void closeWaitForm() {
    myWait.Close();
    MessageBox.Show("Your Process Is Complete");
}
于 2017-07-31T01:03:31.433 に答える
1

load メソッドにあるコードを取得し、それをスレッドに配置します。フォームのどこかに進行状況バーを設定し、データを収集しているコードの重要な段階でそれを増やします。ただし、スレッド自体でこれを行わないように注意してください。つまり、別のスレッドで ui 要素を改ざんしないでください。デリゲートを使用してそれらを呼び出す必要があります。

于 2013-04-02T16:34:36.537 に答える