public partial class Form1 : Form { public class Test : System.ComponentModel.INotifyPropertyChanged { private int m_Count = 0; public int Count { get { return m_Count; } set { m_Count = value; NotifyPropertyChanged("Count"); } } public void Begin() { Thread thread = new Thread(Counter); thread.Start(); } private void Counter() { for (int i = 0; i < 1000; i++) { Count = i; System.Threading.Thread.Sleep(100); } } public void NotifyPropertyChanged(string info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion } public Form1() { InitializeComponent(); Binding binding = new Binding("Text", t, "Count"); label1.DataBindings.Add(binding); } Test t = new Test(); private void button1_Click(object sender, EventArgs e) { t.Begin(); } }
出现的错误是:线程间操作无效: 从不是创建控件“label1”的线程访问它。
请问如何解决呢?
在Form1中设 CheckForIllegalCrossThreadCalls = false;
public Form1() { InitializeComponent(); CheckForIllegalCrossThreadCalls = false; Binding binding = new Binding("Text", t, "Count"); label1.DataBindings.Add(binding); }
除了这种方法,还有其它的方法吗?
如果我是用WPF界面呢?
WPF中的Binding 支持跨线程,不存在这个问题。
还可以用BeginInvoke
public partial class Form1 : Form { public Form1() { InitializeComponent(); t.UIElement = this; Binding binding = new Binding("Text", t, "Count"); label1.DataBindings.Add(binding); } Test t = new Test(); private void button1_Click(object sender, EventArgs e) { t.Begin(); } } public class Test : System.ComponentModel.INotifyPropertyChanged { private int m_Count = 0; public int Count { get { return m_Count; } set { m_Count = value; NotifyPropertyChanged("Count"); } } public void Begin() { Thread thread = new Thread(Counter); thread.IsBackground = true; thread.Start(); } private void Counter() { for (int i = 0; i < 1000; i++) { if (UIElement!=null&&UIElement.IsHandleCreated) { UIElement.BeginInvoke((Action)(() => { Count = i; })); } System.Threading.Thread.Sleep(100); } } public void NotifyPropertyChanged(string info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } public Control UIElement { get; set; } #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion }
调用invoke方法.可以将方法委托传回到UI线程执行.
这是微软的推荐方法,不要关闭线程安全检测,
关键是这个Invoke方法应该如何写,
我不会写啊,你能给出个例子吗?
@luoshupeng: http://msdn.microsoft.com/zh-cn/library/ms171728(v=vs.110).aspx
@吴瑞祥: 谢谢你给的回复,这个在线程中给控件赋值的委托方法我会用。
可是我现在的问题是绑定啊,你看看我的例子。
这个委托的Invoke不会写啊。
@luoshupeng: 上面那个写法是对的,需要把外面的UI控件传到test类里去.