我想将BackgroundWorker用于我的代码。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (worker.CancellationPending == true)
{
e.Cancel = true;
}
else
{
hladat();
}
}
我的函数hladat()是
int x = 0;
while (x < 130)
{
for (trackBar7.Value = x; trackBar7.Value < 250-x; trackBar7.Value += 2)
{
minR = trackBar7.Value;
System.Threading.Thread.Sleep(15);
if (((CV - CV / 4) < RV) && (RV < CV)&&(vyhovujedlzka()))
{
break;
}
}
trackBar7.Value = x;
minR = x;
for (trackBar8.Value = 250 - x; trackBar8.Value > x; trackBar8.Value -= 2)
{
maxR = trackBar8.Value;
System.Threading.Thread.Sleep(15);
if (((CV - CV / 4) < RV) && (RV < CV) && (vyhovujedlzka()))
{
break;
}
}
trackBar8.Value = 250-x;
maxR = 250-x;
for (trackBar9.Value = 0; trackBar9.Value < 254; trackBar9.Value += 2)
{
minG = trackBar9.Value;
System.Threading.Thread.Sleep(15);
if (((CV - CV / 4) < RV) && (RV < CV) && (vyhovujedlzka()))
{
break;
}
}
if (((CV - CV / 4) < RV) && (RV < CV) && (vyhovujedlzka()))
{
break;
}
x = x + 10;
trackBar9.Value = 0;
minG = 0;
}
当我启动bgWorker时,它会给我这部分代码的错误
trackBar7.Value = x
“跨线程操作无效:控制'trackBar7'从其创建的线程以外的线程访问。”
我怎么能修复这段代码??? ... thnx抱歉我的英语= //
答案 0 :(得分:2)
为BackgroundWorker()控件设置WorkerReportsProgress()为True,然后连接ProgressChanged()事件。
现在改变:
trackBar7.Value = x;
要:
backgroundWorker1.ReportProgress(x, trackBar7);
在ProgressChanged()事件中,将e.UserState
强制转换回TrackBar并将其Value()设置为e.Percentage
:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
TrackBar tb = (TrackBar)e.UserState;
tb.Value = e.ProgressPercentage;
}
替代方法:
如果您想在hladat()内部完成所有操作,请更改:
trackBar7.Value = x;
要:
trackBar7.Invoke((MethodInvoker)delegate{
trackBar7.Value = x;
});
答案 1 :(得分:1)
http://msdn.microsoft.com/en-us/library/ms171728%28v=vs.85%29.aspx
使用此功能设置值:
delegate void SetValueCallback(TrackBar trackbar, int value);
private void SetValue(TrackBar trackbar, int value)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (trackbar.InvokeRequired)
{
SetValueCallback d = new SetValueCallback(SetValue);
this.Invoke(d, new object[] {trackbar, value });
}
else
{
trackbar.Value = value;
}
}
这应该纠正set
部分。
阅读;最好将Value
写入变量。在这种情况下,您不需要为您的逻辑访问UI控件,只需读取变量。
类似的东西:
for (int c = x; c < 250-x; c += 2)
{
SetValue(trackBar7, c);
//etc.
答案 2 :(得分:1)
您有几个选项,可以使用Invoke
方法Stefan mentioned,ReportProgress
,例如Idle_Mind mentioned,或者其他选项是使用IProgress<T>
(如果您在.NET 4.0上,您可以从Microsoft.Bcl NuGet包中获取类和接口。
它的工作方式是创建一个Progress<T>
对象并将其设置为在UI线程上执行您需要的任何更新(它捕获当前正在运行的线程的SynchronizationContext
创建它,然后在UI线程上创建它,然后将IProgress<T>
接口传递给您进行更新的方法,该方法调用Report(T)
private Form1()
{
//Snip
trackBar7Progress = new Progress<int>(value => trackBar7.Value = value);
trackBar8Progress = new Progress<int>(value => trackBar8.Value = value);
trackBar9Progress = new Progress<int>(value => trackBar9.Value = value);
}
IProgress<int> trackBar7Progress;
IProgress<int> trackBar8Progress;
IProgress<int> trackBar9Progress;
然后在hladat()
内将trackBar#.Value = x
来电更改为trackBar#Progress.Report(x)
//Snip
trackBar7Progress.Report(x);
minR = x;
for (trackBar8.Value = 250 - x; trackBar8.Value > x; trackBar8.Value -= 2)
{
maxR = trackBar8.Value;
System.Threading.Thread.Sleep(15);
if (((CV - CV / 4) < RV) && (RV < CV) && (vyhovujedlzka()))
{
break;
}
}
trackBar8Progress.Report(250-x);
maxR = 250-x;
for (trackBar9.Value = 0; trackBar9.Value < 254; trackBar9.Value += 2)
{
minG = trackBar9.Value;
System.Threading.Thread.Sleep(15);
if (((CV - CV / 4) < RV) && (RV < CV) && (vyhovujedlzka()))
{
break;
}
}
if (((CV - CV / 4) < RV) && (RV < CV) && (vyhovujedlzka()))
{
break;
}
x = x + 10;
trackBar9Progress.Report(0);
minG = 0;