繁体   English   中英

具有ProgressBar的BackgroundWorker-跨线程操作无效

[英]BackgroundWorker with ProgressBar - Cross-thread operation not valid

我的表格申请中有服务电话。 单击我的按钮后,我将调用我的服务方法。 这是我的代码块:

void listBox_SelectedValueChanged(object sender, EventArgs e)
    {
        if (listBox.SelectedItem.Equals("Demo"))
        {
            progressBar1.Visible = true;
            backgroundWorker1.RunWorkerAsync();
        }
    }

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {   
        ObservableCollection<FilterInfo> filterInfos = new ObservableCollection<FilterInfo>();
        FilterInfo myFilterObj = new FilterInfo("SUPERVISOR", userName);
        filterInfos.Add(myFilterObj);
        ObservableCollection<DEMOBec> demos = demoSvc.GetDemoByFilter(filterInfos, false);
        dt = new Converter<DEMOBec>().ConvertDataTable(demos.ToList());
    }

在调用该服务之前,我使ProgressBar(样式=选取框)可见。 但是由于跨线程问题,我无法使其在完整的方法中不可见。

当我尝试在BGWorker的Completed事件中的UI线程中执行某些操作时,

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        progressBar1.Visible = false;
    }

我有一个例外:

跨线程操作无效:控件“ Form1”从创建该线程的线程之外的线程访问。

我该如何解决这个问题?

您需要使用Invoke()方法

    private delegate void ToDoDelegate();
    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Invoke(new ToDoDelegate(() => progressBar1.Visible = false));
    }

Invoke()的详细信息http://msdn.microsoft.com/de-de/library/System.Windows.Forms.Control.Invoke(v=vs.110).aspx

这是我一直喜欢使用的小段代码,我不记得很久以前将其放在Dropbox中的位置。

public static class ControlExtensions
{
    public static TResult InvokeEx<TControl, TResult>(this TControl control,
                                               Func<TControl, TResult> func)
      where TControl : Control
    {
        return control.InvokeRequired
                ? (TResult)control.Invoke(func, control)
                : func(control);
    }

    public static void InvokeEx<TControl>(this TControl control,
                                          Action<TControl> func)
      where TControl : Control
    {
        control.InvokeEx(c => { func(c); return c; });
    }

    public static void InvokeEx<TControl>(this TControl control, Action action)
      where TControl : Control
    {
        control.InvokeEx(c => action());
    }

}

用法

this.InvokeEx( x => Progressbar1.Visible = false); //Note 'x' could be any variable

这样,您不必每次都键入所有内容,并且使用非常简单。 只需将此权利添加到表单类的末尾(在最后一个括号关闭之后)。 您可以使用它来安全地执行任何跨线程操作。

修改UI线程上ProgressBar的可见性。

Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)
                    delegate()
                    {
                        progressBar1.Visible = false;
                    });

我认为在RunWorkerCompleted事件中不会引发异常(如评论中所述)。 我的建议是,您尝试在DoWork事件中访问UI cmponent的行会触发它。

尝试将DoWork事件中所需的数据放入DoWorkEventArgs e 这样的讨论在SO上提供了大量示例。

工作完成后,也可以使用事件args向“主UI线程”提供已修改/新的数据,如下所示:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
    // do some work
    e.Result = ... ; // modified/new data
}

并以以下方式检索它:

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    var newData = (CastToWhatever) e.Result;
}

希望对您有帮助=)

编辑

您在backgroundWorker1_RunWorkerCompleted()代码绝对不是异常的来源。 它构建了一个简单的示例来说明我的观点:

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync(textBox1.Text);
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var num = Int32.Parse(e.Argument.ToString()) + 1;
    backgroundWorker1.ReportProgress(num);
    e.Result = num;
}

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

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    textBox1.Text = e.Result.ToString();
}

它能做什么? 在WinForm上,有一个带有数字的TextBox ,一个ProgressBar和一个用于启动BackGroundWorkerButton

worker从TextBox (UI线程)获取该数字, DoWork将其增加1并将其保存为result (新线程) 另外,它将增加的数字报告给ProgressBar (跨线程)

最后, RunWorkerCompleted读取结果并将新值存储在TextBox (UI线程)中

因此,请重新检查您的代码;-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM