使用BackgroundWorker进行线程安全调用

时间:2013-11-19 19:11:13

标签: c# multithreading

我想将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抱歉我的英语= //

3 个答案:

答案 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 mentionedReportProgress,例如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;