1

バックグラウンド ワーカーを使用して、sqlserver のいくつかのテーブルを更新しています。プログレスバーの最大値が正しい値に設定され、プログレスバーの値がインクリメントされ、バックグラウンドワーカーのプログレスチェンジが正しい値で正しく呼び出されていますが、バーは進行していません。

これが background_dowork メソッドのフォームのコードです。正しい値で動作する updateProgressBarValue を呼び出すループがあります。

public InterfaceConvertLonLat()
{
    InitializeComponent();
    Shown += new EventHandler(Form1_Shown);
    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
}

public void ConvertLonLat_Load(object sender, EventArgs e)
{ 
}

public void updateProgressBarValue()
{
    progressBar1.Value++;
    backgroundWorker1.ReportProgress(progressBar1.Value);
}

public void setProgressBarMax(int max)
{
    progressBar1.Maximum = max;
    MessageBox.Show("setprogressbarmax " + max);
}

public void Form1_Shown(object sender, EventArgs e)
{     
    backgroundWorker1.RunWorkerAsync();
}

public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    convert.OSGB36ToWGS84("paf");
}

public void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

これは updateprogressbarvalue を呼び出す別のクラスに含まれるループです。これは起動されており、前述のように backgroundworker1_progressChanged が起動されていますが、バーは移動していません。

con.setProgressBarMax(address.Tables[0].Rows.Count); 

foreach (DataRow LonLat in address.Tables[0].Rows)
{
    con.updateProgressBarValue();
    Double lon = 0;
    Double lat = 0;
    lat = Convert.ToDouble(LonLat["LTO"]);
    lon = Convert.ToDouble(LonLat["LGO"]);
    LocalToWGS84(ref lat, ref lon, OGB_M);

    cmd1.Parameters["@LTW"].Value = lat;
    cmd1.Parameters["@LGW"].Value = lon;

    string dbQuery1 = "update " + tableName + " set LTW = @LTW, LGW = @LGW";

    cmd1.CommandText = (dbQuery1);
    cmd1.CommandType = CommandType.Text;
    cmd1.Connection = conn;
    cmd1.ExecuteNonQuery();
}
}
catch (Exception e)
{
    MessageBox.Show("error converting: " + e.Message);
}
finally
{
    conn.Close();
}
4

5 に答える 5

2

進行状況を報告するときは、バックグラウンド ワーカーからイベントを発生させて、進行状況バーに更新が必要であることを伝える必要があります。これは、以下を使用して行うことができます。

backgroundWorker1.ReportProgress(10);

コードの進行状況の増加を示すために必要な値に値を変更します。進行状況の変更イベントは、ほとんどの場合、GUI と同じスレッドで実行されるため、クロス スレッドの問題は発生しません。1 つの例外は、フォームがアドインを介して Excel から呼び出されている場合です。この場合、Excel はメイン スレッドになります。

于 2012-10-02T10:00:29.400 に答える
1

いくつかの問題があります-UpdateprogressBarValue()プログレスバーの値を増やすだけですが、呼び出された回数/現在の値を追跡していません-したがって、101回呼び出すと( 0-100)、あなたは得るでしょうOutOfRangeException

あなたのDoWork()メソッドは、更新をまったく呼び出していないようです(直接またはイベントを発生させることによって)。

イベントを使用してこれを行うことができますが、デリゲートまたはおそらく匿名関数を使用することをお勧めします。何かのようなもの...

public void setProgress(int value) {
    progressBar1.invoke(delegate{ progressBar1.Value = value; }
}

次に、メソッドsetProgress(0)から呼び出すだけですsetProgress(progressBar1.MaxValue)DoWork()

于 2012-10-02T10:19:17.487 に答える
1

以下は重大な誤りです。

public void updateProgressBarValue()
{
    progressBar1.Value++;   // not thread-safe
    backgroundWorker1.ReportProgress(progressBar1.Value);

}

ReportProgress()DoWork から呼び出されることを意図しているため、Control プロパティを読み取ることさえできません。
foreach ループでカウンターを保持し、それを進行メカニズムにフィードする必要があります。

これは、動かない理由を直接示しているわけではありませんが、Completed ハンドラーがありません。プロセスが完全に終了したことを確認しますか?

例外が DoWork をエスケープすると、何が起こったのかわかりません。

于 2012-10-02T11:48:45.203 に答える
0
private void Form1_Load(object sender, System.EventArgs e)
{
    // Start the BackgroundWorker.
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i <= 100; i++)
    {
    // Wait 100 milliseconds.
    Thread.Sleep(100);
    // Report progress.
    backgroundWorker1.ReportProgress(i);
    }
}

private void backgroundWorker1_ProgressChanged(object sender, progress e)
{
    // Change the value of the ProgressBar to the BackgroundWorker progress.
    progressBar1.Value = e.ProgressPercentage;
    // Set the text.
    this.Text = e.ProgressPercentage.ToString();
}
于 2013-02-28T09:00:22.083 に答える
-2

これは、Windows フォームの UI が独自のスレッド/コンテキストで実行されていることが原因であると考えられます。この場合、おそらくInvokeUI を調整するために を使用する必要があります。

このようなもの:

public void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    Invoke(new ProgressDelegate(UpdateProgress), e.ProgressPercentage);
}

delegate void ProgressDelegate(decimal value);

private void UpdateProgress(decimal value)
{
    progressBar1.Value = value;
}
于 2012-10-02T09:29:18.330 に答える