从另一个线程访问对象字段

本文关键字:对象 字段 访问 线程 另一个 | 更新日期: 2023-09-27 18:15:19

我需要访问TimerData。textSet字段,以更改另一个控制定时的线程显示的文本。但是会抛出InvalidOperationException。这个问题有解决办法吗?

namespace Scilca.KBL
{
    public class TimerData
    {
        public Run textSet;
        public ProgressBar statusTimer;
        public TimerData(Run run, ProgressBar statusTimer)
        {
            textSet = run;
            this.statusTimer = statusTimer;
        }
    }
    /// <summary>
    /// Interaction logic for KBLSessionWindow.xaml
    /// </summary>
    public partial class KBLSessionWindow : Window
    {
        private int leftTime = 60;
        private static Run run;
        private static ProgressBar progressBar;
        public int TimeLeftOver
        {
            get { return leftTime; }
        }
        public KBLSessionWindow()
        {
            InitializeComponent();
            run = runSecondTime;
            progressBar = timeProgress;
            Thread timerThread = new Thread(new ParameterizedThreadStart(startTimer));
            timerThread.Start(new TimerData(run, progressBar));
        }
        public void startTimer(Object td)
        {
            TimerData timerData = (TimerData)td;
            int time = 60;
            while (true)
            {
                Thread.Sleep(1000);
                time -= 1;
                if (time == 0)
                    time = 60;
                Console.WriteLine(timerData.textSet.Text);
                timerData.textSet.Text = time.ToString(); // InvalidOperationException
                timerData.statusTimer.Value = time * 100 / 60;
            }
        }
    }
}

从另一个线程访问对象字段

看起来您试图从非UI线程访问UI元素

当你从主线程以外的线程更新UI元素时,你需要使用:

Application.Current.Dispatcher.Invoke(() =>
{
        // your code here.
        timerData.textSet.Text = time.ToString();
        timerData.statusTimer.Value = time * 100 / 60;
});

否则你将得到一个系统。InvalidOperationException

从MSDN:

一个系统。当对象的状态不支持方法调用时调用对象的方法时抛出InvalidOperationException。当方法试图从非主线程或UI线程的线程操作UI时,也会抛出该异常。

与你的问题无关,我建议使用计时器(见下文)而不是每次创建一个新线程,这将更有效,因为计时器正在使用线程池:

Timer myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler(DisplayTimeEvent);
myTimer.Interval = 1000; // 1000 ms is one second
myTimer.Start();
public static void DisplayTimeEvent(object source, ElapsedEventArgs e)
{
    // code here will run every second
}