私は次の問題を抱えています:
MainFormという名前のフォームがあります。私はこのフォームで行われる長い操作があります。
この長い操作が行われている間、MainFormの上にProgressFormという名前の別のものを表示する必要があります。
ProgressFormには、長い操作が行われている間に更新する必要があるプログレスバーが含まれています。
長い操作が完了すると、ProgressFormは自動的に閉じられます。
私は次のコードを書きました:
_using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ClassLibrary
{
public class MyClass
{
public static string LongOperation()
{
Thread.Sleep(new TimeSpan(0,0,30));
return "HelloWorld";
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace BackgroungWorker__HelloWorld
{
public partial class ProgressForm : Form
{
public ProgressForm()
{
InitializeComponent();
}
public ProgressBar ProgressBar
{
get { return this.progressBar1; }
set { this.progressBar1 = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ClassLibrary;
namespace BackgroungWorker__HelloWorld
{
public partial class MainForm : Form
{
ProgressForm f = new ProgressForm();
public MainForm()
{
InitializeComponent();
}
int count = 0;
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (f != null)
{
f.ProgressBar.Value = e.ProgressPercentage;
}
++count;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("The task has been cancelled");
}
else if (e.Error != null)
{
MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());
}
else
{
MessageBox.Show("The task has been completed. Results: " + e.Result.ToString());
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (f == null)
{
f = new ProgressForm();
}
f.ShowDialog();
//backgroundWorker1.ReportProgress(100);
MyClass.LongOperation();
f.Close();
}
private void btnStart_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void btnCancel_Click(object sender, EventArgs e)
{
backgroundWorker1.CancelAsync();
this.Close();
}
}
}
_
progressBar
を更新する方法が見つかりません。
backgroundWorker1.ReportProgress()
をどこに配置すればよいですか?また、これをどのように呼び出す必要がありますか?
アプリケーションのこのレイヤーで操作が完了するまでに何が起こるか、またはどのくらいの時間がかかるかわからないため、MyClass
を変更してはなりません。
誰か助けてもらえますか?
1つの問題はあなたが30秒間眠っているということです。通常、長時間実行されるタスク内のさまざまなポイントでReportProgress
を呼び出します。したがって、これを示すために、コードを1秒間スリープするように変更することもできますが、30回、スリープが終了するたびにReportProgress
を呼び出します。
もう1つの問題は、ProgressForm
fromバックグラウンドスレッドを表示していることです。 [〜#〜] ui [〜#〜]スレッドで開始する必要がありますが、バックグラウンドワーカーのProgressChanged
イベントをフックします。その後、バックグラウンドワーカーが進捗状況を報告すると、進捗状況フォームが更新されます。
設定する必要があることに注意してください
backgroundWorker1.WorkerReportsProgress = true;
バックグラウンドワーカーにProgressChangedイベントを発生させたい場合
backgroundWorker1.WorkerSupportsCancellation = true;
ワーカースレッドをキャンセルできるようにしたい場合。
他の人が言っているように、UIスレッドでf.ShowDialog()を実行し、ProgressChangedを使用してProgressWindowを更新します。
ProgressFormを自動的に閉じるには、backgroundWorker1_RunWorkerCompletedでf.Close();を呼び出します。これは、長い操作が完了し、ウィンドウを閉じることができることを意味します。
ReportProgressは、「working」メソッドで呼び出す必要のあるメソッドです。このメソッドは「ProgressChanged」イベントを発生させます。
フォームでは、イベントハンドラーをProgressChangedイベントにアタッチできます。そのイベントハンドラー内で、プログレスバーの位置を変更できます。イベントハンドラーをRunWorkerCompletedイベントにアタッチすることもでき、そのイベントハンドラー内で、プログレスバーを含むフォームを閉じることができます。
ここで必要なのは、メインフォーム全体をクラスに渡すのではなく、単にBackgroundWorkerのインスタンスに渡すことです。次のように、送信者をバックグラウンドワーカーとしてキャストする必要があります。
_private void bgWorker_DoWork(object sender DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event
BackgroundWorker worker = sender as BackgroundWorker;
// And now you just send worker to whatever class you need like so:
bgArgs args = e.Argument as bgArgs;
MyClass objMyClass = new MyClass();
MyClass.MyMethod(strValue, args.Option, worker);
// Do something based on return value.
}
_
次に、MyClass.MyMethod()
で進行状況の計算を行い、worker.ReportProgress(int percentage)
イベントを発生させて、メインUIフォームの進行状況バーなどを更新します。
これは完全に機能するはずです!
詳細については、このMSDNの記事を確認してください。フィボナッチの例を参照してください。CalculateFibonacci
はメインフォームのUIに更新を送信するカスタムクラスであるため、これが実行されます。
詳細については、 MSDN BackgroundWorker Class を参照してください。