积极答复者
控件Invoke方法的疑问

问题
-
以下是为了在UI线程中显示数据; 是有另一个线程使用这个函数; 为了解决在一个线程中访问另一个线程控件的问题.
我现在的疑问是, AddMessageDelegate d = AddMessage; 这貌似是委托指向了自身.
这一句; 为何不如注释中我所写句子那样用呢
完整程序如下:
----------------------------------------------------------------------------------
using System.Threading;
namespace ThreadExample
namespace ThreadExample
{
class Class1
{
public volatile bool shouldStop;
private Form1 form1;
public Class1(Form1 form1)
{
this.form1 = form1;
}
public void Method1(object obj)
{
string s = obj as string;
form1.AddMessage(s);
form1.AddMessage("a");
// while (shouldStop == false)
// {
// Thread.Sleep(100); //线程1休眠100毫秒
// form1.AddMessage("a");
// }
form1.AddMessage("\n线程Method1已终止");
}
public void Method2()
{
form1.AddMessage("b");
// while (shouldStop == false)
//{
// Thread.Sleep(100); //线程2休眠100毫秒
// form1.AddMessage("b");
//}
form1.AddMessage("\n线程Method2已终止");
}
}
}
----------------------------------------------------------------------------------------------
{
public partial class Form1 : Form
{
Thread thread1, thread2;
Class1 class1;
public Form1()
{
InitializeComponent();
class1 = new Class1(this);
buttonStart.Click += new EventHandler(buttonStart_Click);
buttonStop.Click += new EventHandler(buttonStop_Click);
}
private void buttonStart_Click(object sender, EventArgs e)
{
richTextBox1.Clear();
class1.shouldStop = false;
thread1 = new Thread(class1.Method1);
thread1.IsBackground = true;
thread2 = new Thread(class1.Method2);
thread2.IsBackground = true;
thread1.Start("a method start\n");
thread2.Start();
// Thread t = new Thread(new ThreadStart(SetLbText));
Thread t = new Thread(SetLbText);
t.Start();
}
private void buttonStop_Click(object sender, EventArgs e)
{
class1.shouldStop = true;
thread1.Join(0);
thread2.Join(0);
}
private delegate void AddMessageDelegate(string message);
public void AddMessage(string message)
{
if (richTextBox1.InvokeRequired)
{
AddMessageDelegate d = AddMessage;
richTextBox1.Invoke(d, message);
//AddMessageDelegate d = (string isr) => { richTextBox1.Text = isr; };
//richTextBox1.Invoke(d, "test"); 我试图修改之处
}
else
{
richTextBox1.AppendText(message);
}
}
}
}
答案
-
你好,
按照你没有注释的语句,有问题吗?我测试过完全可以啊(简化了测试代码):
public partial class Form1 : Form { private delegate void AddMessageDelegate(string message); public void AddMessage(string message) { if (richTextBox1.InvokeRequired) { AddMessageDelegate d = AddMessage; richTextBox1.Invoke(d, message); } else { richTextBox1.AppendText(message); } } public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { Thread th = new Thread(() => { AddMessage("aaa"); }); th.IsBackground = true; th.Start(); } }
不过有一个问题需要注意——第一次(即Thread.Start之后调用那个AddMessage),此时InvokeRequired=true,此时使用Control.Invoke(……),那么方才InvokeRequired=false- 已标记为答案 Bob ShenModerator 2012年10月2日 7:29
全部回复
-
你好,
按照你没有注释的语句,有问题吗?我测试过完全可以啊(简化了测试代码):
public partial class Form1 : Form { private delegate void AddMessageDelegate(string message); public void AddMessage(string message) { if (richTextBox1.InvokeRequired) { AddMessageDelegate d = AddMessage; richTextBox1.Invoke(d, message); } else { richTextBox1.AppendText(message); } } public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { Thread th = new Thread(() => { AddMessage("aaa"); }); th.IsBackground = true; th.Start(); } }
不过有一个问题需要注意——第一次(即Thread.Start之后调用那个AddMessage),此时InvokeRequired=true,此时使用Control.Invoke(……),那么方才InvokeRequired=false- 已标记为答案 Bob ShenModerator 2012年10月2日 7:29
-
谢谢,我后来看了下委托和事件,我的理解如下,请帮忙参考是不是对的:
private delegate delAaa(string msg);
public void addMsg(string msg)
{
if (textbox1.invokeRequired)
{
delAaa d = addMsg;
textbox1.Invoke(d,msg); //此处只是在创建textbox1的线程中启动委托方法addMsg();
}
else
textbox1.AppendText(msg); // /该adMsg方法在创建textbox1的线程被调用,执行把msg加到textbox1中去
}
Poly(175261789) 22:18:03
是这样的吧,即该addMsg()先在其他线程中被调用,然后在控件线程被再次调用,被执行2次。