【问题标题】:How to run a progress bar in different thread in WPF?如何在 WPF 的不同线程中运行进度条?
【发布时间】:2011-02-02 06:39:51
【问题描述】:

我正在动态填充列表视图项。同时我想显示一个进度条。填充数据时,应禁用进度条。如何实现这一点。 我是 WPF 的新手。

【问题讨论】:

    标签: wpf multithreading .net-4.0 progress-bar


    【解决方案1】:

    您可以使用 BackgroundWorker 类,它可以在您使用 WPF 时简化后台线程的处理。 网上有很多这方面的例子。这里有两个来自 codeproject,但很容易找到更多示例:

    http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo.aspx http://www.codeproject.com/KB/cpp/BackgroundWorker_Threads.aspx

    【讨论】:

    • 但是当我访问后台工作者中的控件时,它会抛出异常:调用线程无法访问此对象,因为不同的线程拥有它。
    • 你必须使用BackgroundWorker事件(ProgressChanged、RunWorkerCompleted)来更新progressBar控件。在这些事件的处理程序中,您可以毫无问题地访问 UI 控件。 msdn.microsoft.com/en-us/library/…
    【解决方案2】:

    我更喜欢通过演示模型来控制视图状态。当视图需要将地址中的项目填充到启动 Worker 线程并在 UI 同步上下文上更新其进度值的表示模型时。

    public class SampleModel : ObservableObject
    {
        private ObservableCollection<string> _items = new ObservableCollection<string>();
        public IEnumerable<string> Items
        {
            get
            {
                return this._items;
            }
        }
    
        private int _progress;
        public int Progress
        {
            get
            {
                return this._progress;
            }
            set
            {
                if (this._progress != value)
                {
                    this._progress = value;
                    this.OnPropertyChanged("Progress");
                }
            }
        }
    
        public void Fill()
        {
            this.Progress = 0;
            var sc = SynchronizationContext.Current;
    
            new Thread(new ThreadStart(() =>
                {
                    for (int i = 0; i < 100; i++)
                    {
                        sc.Post(p =>
                            {
                                this._items.Add(i.ToString());
                                this.Progress ++;
                            }, null);
                        Thread.Sleep(100);
                    }
    
                    sc.Post(p =>
                    {
                        this.Progress = 0;
                    }, null);
    
                }))
                .Start();
        }
    }
    

    XAML:

    <DockPanel>
        <ProgressBar Minimum="0"
                     Maximum="100"
                     Height="50"
                     Value="{Binding Progress}"
                     DockPanel.Dock="Top">
            <ProgressBar.Style>
                <Style TargetType="ProgressBar">
                    <Setter Property="IsEnabled"
                            Value="True"/>
                </Style>
            </ProgressBar.Style>
        </ProgressBar>
        <Button Name="Start"
                DockPanel.Dock="Top">Start</Button>
        <ListView Name="List" 
                  ItemsSource="{Binding Items}"/>
    </DockPanel>
    

    以及后面的代码:

        public MainWindow()
        {
            InitializeComponent();
            this.Model = new SampleModel();
            this.Start.Click += new RoutedEventHandler(Start_Click);
        }
    
        void Start_Click(object sender, RoutedEventArgs e)
        {
            this.Model.Fill();
        }
    
        protected SampleModel Model
        {
            get
            {
                return (SampleModel)this.DataContext;   
            }
            set 
            {
                this.DataContext = value;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      • 2019-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多