我正在使用后台工作程序来更新sqlserver中的一些表。进度条最大值被设置为正确的值,进度条值正在递增,正确调用backgroundworker progresschanged正确值,但条形图没有进展。
这是表单的代码 在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,这是被触发的,正如所述的那样,kickworker1_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();
}
答案 0 :(得分:2)
报告进度时,您需要从后台工作程序触发事件以告知需要更新的进度条。这可以使用以下方法完成:
backgroundWorker1.ReportProgress(10);
将值更改为您需要的代码,以显示代码中增加的进度。进度更改事件将主要在与GUI相同的线程上运行,因此您应该没有跨线程问题。一个例外是如果您的表单是通过插件从Excel调用的,在这种情况下,Excel将位于主线程上。
答案 1 :(得分:1)
你遇到了很多问题 - 你的UpdateprogressBarValue()
只是增加了进度条的值,但没有跟踪它被调用的次数/当前值是多少 - 所以如果你打电话它是101次(假设范围为0-100),你将获得OutOfRangeException
您的DoWork()
方法似乎根本没有调用更新(直接或通过引发事件)。
您可以使用事件来执行此操作,但您最好使用委托或匿名函数。有点像...
public void setProgress(int value) {
progressBar1.invoke(delegate{ progressBar1.Value = value; }
}
然后从setProgress(0)
方法
setProgress(progressBar1.MaxValue)
至DoWork()
答案 2 :(得分:1)
以下是严重错误:
public void updateProgressBarValue()
{
progressBar1.Value++; // not thread-safe
backgroundWorker1.ReportProgress(progressBar1.Value);
}
ReportProgress()
旨在被称为DoWork,它甚至不应该读取Control属性
您应该在foreach循环中维护一个计数器并将其提供给进度机制。
现在这并没有直接表明它为什么不移动但你没有一个已完成的处理程序。你确定这个过程完成了吗?
如果异常逃脱了您的DoWork,您永远不会知道发生了什么。
答案 3 :(得分: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();
}
答案 4 :(得分:-2)
我认为这可能是因为Windows窗体中的UI在其自己的线程/上下文中运行。在这种情况下,您可能需要使用Invoke
来调整UI。
这样的事情:
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;
}