如何从另一个线程更新控件?

时间:2011-06-28 18:18:23

标签: wpf

我有一个简单的wpf应用程序。我需要从另一个线程更新控件。 这是我的代码

namespace WpfApplication1
{
    class Stock
    {
        public int StockId { get; set; }
        public string Name { get; set; }
    }

    class ThreadManager
    {
        public AddMoscowItem MoscowDelegate { get; set; }
        public AddLondonItem LondonDelegate { get; set; }
        public AddNewYorkItem NyDelegate { get; set; }

        public ThreadManager()
        {
            InitStocks();
        }

        private static  readonly object  lockObject = new object();

        private  Stock[] stocks;

        public ThreadManager(AddMoscowItem moscowDelegate, AddLondonItem londonDelegate, AddNewYorkItem nyDelegate)
        {
            MoscowDelegate = moscowDelegate;
            LondonDelegate = londonDelegate;
            NyDelegate = nyDelegate;
        }

        private void InitStocks()
        {
            if (stocks == null)
                lock (lockObject)
                {
                    if (stocks == null)
                        stocks = new Stock[]
                                     {
                                         new Stock() {Name = "Moscow", StockId = 1},
                                         new Stock() {Name = "London", StockId = 2},
                                         new Stock() {Name = "NY", StockId = 3}
                                     };
                }
        }

        public void RunStocks()
        {
            //here we must call methods: AddMoscowListBoxItem, AddLondonListBoxItem
            //how to do it linking to corresponding stock?
        }
    }

    public delegate void AddMoscowItem(string msg);
    public delegate void AddLondonItem(string msg);
    public delegate void AddNewYorkItem(string msg);

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private AddMoscowItem moscowDelegate;
        private AddLondonItem londonDelegate;
        private AddNewYorkItem nyDelegate;

        public MainWindow()
        {
            InitializeComponent();

            moscowDelegate = AddMoscowListBoxItem;
            londonDelegate = AddLondonListBoxItem;
            nyDelegate = AddNYListBoxItem;
            RunThreads();
        }

        public void RunThreads()
        {
            ThreadManager stockThreads = new ThreadManager(moscowDelegate, londonDelegate, nyDelegate);
            stockThreads.RunStocks();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

        }

        public void AddMoscowListBoxItem(string msg)
        {
            if (this.lbxMoscow.Dispatcher.Thread == Thread.CurrentThread)
            {
               lbxMoscow.Items.Add(msg);
            }
            else
            {
                lbxMoscow.Dispatcher.Invoke(DispatcherPriority.Background, new DispatcherOperationCallback(
                                            delegate { lbxMoscow.Items.Add(msg);
                                                         return null;
                                            }), null);
            }
        }

        public void AddLondonListBoxItem(string msg)
        {
            if (this.lbxLondon.Dispatcher.Thread == Thread.CurrentThread)
            {
                lbxLondon.Items.Add(msg);
            }
            else
            {
                lbxLondon.Dispatcher.Invoke(DispatcherPriority.Background, new DispatcherOperationCallback(
                                            delegate
                                            {
                                                lbxLondon.Items.Add(msg);
                                                return null;
                                            }), null);
            }
        }

        public void AddNYListBoxItem(string msg)
        {
            if (this.lbxNY.Dispatcher.Thread == Thread.CurrentThread)
            {
                lbxNY.Items.Add(msg);
            }
            else
            {
                lbxNY.Dispatcher.Invoke(DispatcherPriority.Background, new DispatcherOperationCallback(
                                            delegate
                                            {
                                                lbxNY.Items.Add(msg);
                                                return null;
                                            }), null);
            }
        }
    }
}

任何建议都是合适的!

1 个答案:

答案 0 :(得分:5)

WPF控件具有线程关联性,因此您无法从另一个线程更新其状态。您必须使用控件的Dispatcher将更新封送到UI线程。例如,要更新TextBox:

textBox.Dispatcher.Dispatcher.Invoke(
      System.Windows.Threading.DispatcherPriority.Normal,
      new Action(
        delegate()
        {
          textBox.Text = "Hello World";
        }
    ));