c# 子线程如何通知主线程,使主线程做出响应?

wo8cj 2009-02-27 03:32:56
我要实现的功能如下:

程序中有2个线程,主线程和子线程,
主线程中有一个变量:X
主线程运行中激活子线程,子线程会做出计算改变 X 的值,
主线程继续做其它的事,直到 X 的值发生改变时,才会响应,并在textbox中输出 X 的值(这一过程中主线程并不知道何时X的值才会变,它不能循环等待,必须去做别的事,比如接收用户点击等等)。

这个功能看起来简单,但是我始终找不到方法,我对委托和事件理解的还不透,不知道能不能用事件解决?
期待各位高手解答

...全文
4205 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
lingopen 2011-01-26
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 projectdd 的回复:]
用就
Form.Invoke(Delegae d);
这个方法就可以,你在子线程中改变检查到某个值时候通知主线程就可以了
让改变发生在 参数d所指向的那个方法中就可以了;
[/Quote]
我也遇到类似问题,我的执行顺序是
1.主线程 创建一个窗体mForm对象并Show();
2.开启一个新的子线程,子线程指向循环方法DoFor(),控制mForm中的TextBox.Text显示;
3.当循环完毕后,我想关闭Close()由主线程创建的mForm,这时和楼主类似的问题出现了,我希望在子线程循环方法DoFor()中的for()循环结束后加上 mForm.Close();但这里会提示mForm不是当前线程创建的对象,于是采用invoke方法,顺利解决,部分代码如下:


myForm mForm= null;//myForm是之前定义的一个窗体类
private delegate void OnClose();//定义委托
//省略其他代码。。。
//主线程按钮点击事件
private void button1_Click(object sender, EventArgs e)
{
//创建弹出窗体
mForm= new myForm (true, 1, 100, ProgressBarStyle.Continuous);
mForm.Show();
//新线程
Thread mThread = new Thread(new ThreadStart(DoFor));
mThread.Start();
}
private void DoFor()
{
for (int i = 1; i <= 100; i++)
{
System.Threading.Thread.Sleep(10);
mForm.OnSetValue(i);//这里改变弹出窗口的一个TextBox的Text属性
}
//循环结束后
this.Invoke(new OnClose(DoClose));//子线程中关闭主线程创建的对象

}
//委托指向的方法
private void DoClose()
{
mForm.Close();
}
}

希望对你有帮助!
RFEZGC 2009-03-03
  • 打赏
  • 举报
回复
开启一个新的线程就行了,只要X的值发生改变,就激发一个事件,要自定义个事件
bomdy 2009-03-03
  • 打赏
  • 举报
回复
不好意思,刚才有点错误

public delegate void SetIntValue(int value);

public void setX(int value)
{
if (InvokeRequired)
{
// 在子线程中调用此方法时,通过Invoke转成主线程执行
Invoke(new SetIntValue(setX), value);
return;
}

// 设置X值并显示
X = value;
textbox.Text = X.toString();
}
bomdy 2009-03-03
  • 打赏
  • 举报
回复

public delegate void SetIntValue(int value);

public void setX(int value)
{
if (InvokeRequired)
{
// 在子线程中调用此方法时,通过Invoke转成主线程执行
Invoke(new SetIntValue(value));
return;
}

// 设置X值并显示
X = value;
textbox.Text = X.toString();
}

ProjectDD 2009-03-03
  • 打赏
  • 举报
回复
用就
Form.Invoke(Delegae d);
这个方法就可以,你在子线程中改变检查到某个值时候通知主线程就可以了
让改变发生在 参数d所指向的那个方法中就可以了;
  • 打赏
  • 举报
回复
子线程可以操作界面的啊
xjwangbb 2009-03-03
  • 打赏
  • 举报
回复
可以用自带的BackgroundWorker控件来实现 动态创建它
wo8cj 2009-03-03
  • 打赏
  • 举报
回复
楼上说的我大概明白,但是我要在textbox中输出 X 的值必须由主线程完成,也就是说主线程是一个窗口类,它才能完成显示输出的功能,子线程只负责计算。
4楼的代码:
while (true)
{
if (myResetEvent.WaitOne())
{
Console.WriteLine("After child thread set X, X is " + X);
myResetEvent.Reset();
}
}

这一段是否是要求主线程一直等待? 我的意思是主线程不能等待,还要去处理别的事,直到得到通知才去处理输出。
yingmu 2009-03-01
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 agentianle 的回复:]
引用 2 楼 tmxk2002 的回复:
将X封装成属性

在Set里写入需要触发的代码不就可以了?不一定要主线程去做,子线程当然也可以做的。


推荐这种做法,封装一个事件,形如OnXChanged,主线程中注册此事件,事件触发时就会转到对应代码执行去了。

当然,此时仍是在子线程中执行的。

如一定要主线程去做事,考虑使用信号量、WatiHandle等线程同步机制吧
[/Quote]
同意,实际上就是开放X的访问器。至于显示,简单点,还是不要让主线程去做的好。
天乐 2009-03-01
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 tmxk2002 的回复:]
将X封装成属性

在Set里写入需要触发的代码不就可以了?不一定要主线程去做,子线程当然也可以做的。
[/Quote]

推荐这种做法,封装一个事件,形如OnXChanged,主线程中注册此事件,事件触发时就会转到对应代码执行去了。

当然,此时仍是在子线程中执行的。

如一定要主线程去做事,考虑使用信号量、WatiHandle等线程同步机制吧
zjuter 2009-02-27
  • 打赏
  • 举报
回复
static void Main(string[] args)
{
ManualResetEvent myResetEvent = new ManualResetEvent(false);

int X = 0;

Thread childThread = new Thread(delegate()
{
//Console.WriteLine(Thread.CurrentThread.Name + " " + Thread.CurrentThread.ManagedThreadId);

Console.WriteLine("Set X Value");
X = 10;
Console.WriteLine("Set X Value end");

Console.WriteLine("Notice main thread");
myResetEvent.Set();
});

childThread.Start();

while (true)
{
if (myResetEvent.WaitOne())
{
Console.WriteLine("After child thread set X, X is " + X);
myResetEvent.Reset();
}
}

Console.ReadKey();
}

这里主要是ManualResetEvent的应用,和前面的兄弟提到的autoresetevent 是差不多的,区别自己看下msdn
北京的雾霾天 2009-02-27
  • 打赏
  • 举报
回复
你这也是委托的问题,参考一下:

private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(aa);
th.Start();
}

delegate void somedle();
private void aa()
{
if (this.InvokeRequired)
{
somedle sd = new somedle(aa);
this.Invoke(sd);
return;
}
ShowChar('A');
}
public void ShowChar(char ch)
{
lock (this)
{
textBox1.Text += ch;
}
}
  • 打赏
  • 举报
回复
将X封装成属性

在Set里写入需要触发的代码不就可以了?不一定要主线程去做,子线程当然也可以做的。
jietuan 2009-02-27
  • 打赏
  • 举报
回复
autoresetevent 试试

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧