尝试从另一个线程修改UI时出现InvalidOperationException

时间:2017-07-05 18:13:34

标签: c# winforms binding

我有一个绑定到包含timer.Enabled状态的属性的复选框。

的MainForm:

chbTimer.DataBindings.Add(new Binding("Checked", _inactividadController, "TimerEnabled")
            {
                DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged,
                ControlUpdateMode = ControlUpdateMode.OnPropertyChanged
            });

_inactividadController:

public bool TimerEnabled
    {
        get { return _timer.Enabled; }
        set
        {
            _timer.Enabled = value;
            InvokePropertyChanged(new PropertyChangedEventArgs("TimerEnabled"));
        }
    }

_timer.Elapsed:

private void Test(object sender, ElapsedEventArgs e)
    {
        TimerEnabled = false;
    }

此处发生异常:

public event PropertyChangedEventHandler PropertyChanged;

    public void InvokePropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)  
                  handler(this, e); //<-- BOOM
    }

我完全理解这里发生了什么:Timer在另一个线程上运行并尝试更新主线程上的chbTimer,这是一个非法的操作。但我不知道如何解决这个问题。

尝试this方法但不起作用,因为来自UI的更改未反映在绑定上(当用户选中复选框时,计时器不会更改状态)。

有什么建议吗?感谢

1 个答案:

答案 0 :(得分:1)

修改了InactividadController的构造函数,使其收到SynchronizationContext

在Form.cs上

_inactividadController = new InactividadController(SynchronizationContext.Current);

并修改了INotifyPropertyChanged的实现

public void InvokePropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            _originalContext.Post(delegate
            {
                handler(this, e);
            }, null);
        }
    }