有一个窗体为Form1,其上有一个Label(label1)控件及Botton(button1)控件.同时有一个类为Event,其中有一个事件为TimeUp.
现有一个问题是:我在Form1订阅了TimeUp事件,想在其上更改label1.text内容.代码如下:
窗体代码为:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace EvenExcise
{
public partial class Form1 : Form
{
int Times = 0;
public Form1()
{
InitializeComponent();
this.label1.Text="";
} private void button1_Click(object sender, EventArgs e)
{
Event myEvent = new Event();
myEvent.TimeUp += new Event.EventHappenHandle(myEvent_TimeUp);
} void myEvent_TimeUp(object sender, EventArgs e)
{
Times++;
this.label1.Text = "这是第" + (Times + 1).ToString() + "时间到";
}
}
}Event类的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;namespace EvenExcise
{
class Event
{
System.Timers.Timer myTimer = new System.Timers.Timer(1000);
public delegate void EventHappenHandle(object sender, EventArgs e);
public event EventHappenHandle TimeUp;
public Event()
{
myTimer.Start();
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
} void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
EventArgs ee = new EventArgs();
TimeUp(sender, ee);
} }
}可为什么一运行到this.label1.Text = "这是第" + (Times + 1).ToString() + "时间到";
出错,提示如下:"线程间操作无效: 从不是创建控件“label1”的线程访问它。"
难道这种情况只能采用.invoke, 用代理方法处理,如是这样,如我要对窗体中的许多控件外观进行处理,不是要定义许多代理?
请高手指导,谢谢!
现有一个问题是:我在Form1订阅了TimeUp事件,想在其上更改label1.text内容.代码如下:
窗体代码为:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace EvenExcise
{
public partial class Form1 : Form
{
int Times = 0;
public Form1()
{
InitializeComponent();
this.label1.Text="";
} private void button1_Click(object sender, EventArgs e)
{
Event myEvent = new Event();
myEvent.TimeUp += new Event.EventHappenHandle(myEvent_TimeUp);
} void myEvent_TimeUp(object sender, EventArgs e)
{
Times++;
this.label1.Text = "这是第" + (Times + 1).ToString() + "时间到";
}
}
}Event类的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;namespace EvenExcise
{
class Event
{
System.Timers.Timer myTimer = new System.Timers.Timer(1000);
public delegate void EventHappenHandle(object sender, EventArgs e);
public event EventHappenHandle TimeUp;
public Event()
{
myTimer.Start();
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
} void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
EventArgs ee = new EventArgs();
TimeUp(sender, ee);
} }
}可为什么一运行到this.label1.Text = "这是第" + (Times + 1).ToString() + "时间到";
出错,提示如下:"线程间操作无效: 从不是创建控件“label1”的线程访问它。"
难道这种情况只能采用.invoke, 用代理方法处理,如是这样,如我要对窗体中的许多控件外观进行处理,不是要定义许多代理?
请高手指导,谢谢!
form2中定义了
public delegate void UpdateNotice(string NoticeText);//更新notice的委托用
public UpdateNotice AppNoticeByThread;
前台的目的是希望直接修改
public void AppNotice(string msg)
{
this.Notice.AppendText(msg + "\n");
}后台一个线程已启动,想更新form2 ,如何才能做到通过调用public void AppNotice(string msg)实现?
public delegate void UpdateNotice(string NoticeText);//更新notice的委托用
public event UpdateNotice AppNoticeByThread;void RunThread()
{
Debug.Print("thread is run");
if (AppNoticeByThread != null)
{
AppNoticeByThread("new text");
}
}
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(new ThreadStart(RunThread));
th.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
this.AppNoticeByThread += new UpdateNotice(Form1_AppNoticeByThread);
}//其他线程改变主线程中的控件状态
void Form1_AppNoticeByThread(string NoticeText)
{
if (textBox1.InvokeRequired)
{
textBox1.Invoke(new UpdateNotice(Form1_AppNoticeByThread),new object[]{NoticeText});
}
else
{
textBox1.Text = NoticeText;
}
}
http://topic.csdn.net/u/20100503/13/0503b79e-8a17-4ea0-98c0-c7f886c77a8b.html?seed=1691679054&r=65144079#r_65144079
private delegate void showTime(string timeStr);
void myEvent_TimeUp(object sender, EventArgs e)
{
Times++;
showTime s = new showTime(ShowTime);
this.invoke(s, new object[]{Times.toString()});
}
private void ShowTime(string times)
{
this.label1.Text = "这是第" + times + "时间到";
}
未测试,应该OK的
{
Times++;
CrossThreadOperationControl CrossDelete = delegate()
{
this.label1.Text = "这是第" + (Times + 1).ToString() + "时间到";
};
label1.Invoke(CrossDelete);
}
修改myEvent_TimeUp的实现,就可以了!
上面的方法都不错
还有一个
public Form1(){
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;//加上这句就OK了。哈哈
}
把要改的数据定义一个结构体或者类来暂存,然后用SendMessage给自己发送修改消息。
在defwndproc中拦截消息,读出修改的值,赋给各个控件。
自己去尝试吧。
禁止:检查非法的跨线程调用
是否在Event类中增加属性(如TimeUpPro),产生事件时设置其值.再在Form1中利用定时器扫描TimeUpPro,根据对应值作相应的处理呢?
这个方法最简单,如果没有多个线程同时修改的话,就可以用这个了。
如果有多个线程修改一个控件,就不能这样了,必须做线程同步!
不知有什么好的方法?
我这两次发了贴,你都很快回复了,对我的提问也回答得较充分,谢谢!