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

时间:2016-10-27 14:00:55

标签: c# .net multithreading

我需要访问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;
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

看起来您正在尝试从非ui线程访问UI元素。

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

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

否则您将获得System.InvalidOperationException

来自MSDN:

  

当对象的状态不支持方法调用时调用对象的方法时,抛出System.InvalidOperationException。当方法尝试从不是主线程或UI线程的线程操作UI时,也会抛出异常。

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

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
}