线程间通信问题!!!

jweet 2008-07-09 11:27:41
我在窗口中写了一个异步委托,让后在异步委托中又创建了几个线程来执行数据导入,现在我想要实现,当数据导入完毕后,哪几个现场中的随便以一个通知委托已完成导入功能,最后在界面上弹出窗口。。谢谢。!!各位~~~
...全文
172 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
wxm4585 2008-07-14
  • 打赏
  • 举报
回复
Join()和WaitOne()在自己单独线程运行,怎么会导致主线程挂起?

估计没人会把这两个方法放在UI线程里吧,会影响用户体验?

要用事件订阅,并不是一定不能实现这个功能,但肯定不会比用ManualResetEvent简单。

你下…
[/Quote]
暂且不论挂起,阻塞和假死的字面区别,自己试验一下就知道Join和WaitOne的效果了,要想在调用的过程中,程序仍然可以正常做其它的工作,就必须使用异步调用的方式。至于启动一个或者多个线程来回调,是没有本质的区别的,应注意,新开的线程要显示指定为后台线程。
marvelstack 2008-07-12
  • 打赏
  • 举报
回复
这个实现可以参考下面类似的例子。
http://blog.csdn.net/zhzuo/archive/2004/06/15/22038.aspx
nealwike 2008-07-11
  • 打赏
  • 举报
回复
mark
我很懒 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 sb_CJ_sx 的回复:]
用Join和ManualResetEvent都可以实现,下面写了个简单的例子,假设用3个线程来完成
数据导入,其中方法StartTest1()和Method1()用Join实现功能,方法StartTest2()和
Method2()用ManualResetEvent实现功能.

class Program {
static ManualResetEvent m_Event = new ManualResetEvent(false);
static int m_EndedThreadCount = 0;

static void Main() {
Thread thread = new…
[/Quote]
fuadam 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 jweet 的回复:]
每个线程都会执行MyMethod2 方法,那不是要调用三次m_Event.Set(); ,那么主线程中是否也会相应三次呢?
[/Quote]

//每个线程在完成任务后进行判断,如果为了说明所有线程执行完毕
if (Interlocked.Decrement(ref num) == 0)
e.Set();
jweet 2008-07-10
  • 打赏
  • 举报
回复
每个线程都会执行MyMethod2 方法,那不是要调用三次m_Event.Set(); ,那么主线程中是否也会相应三次呢?
sb_CJ_sx 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wxm4585 的回复:]
又接着试了一下ManualResetEvent,发现也导致了主线程的挂起,不太理解为什么要这么处理,如果在等待副线程处理完成时挂起了主线程,那这样的多线程还有什么意义?
[/Quote]

Join()和WaitOne()在自己单独线程运行,怎么会导致主线程挂起?

估计没人会把这两个方法放在UI线程里吧,会影响用户体验?

要用事件订阅,并不是一定不能实现这个功能,但肯定不会比用ManualResetEvent简单。

你下面的程序我看了,LZ的意思是分别在几个线程里面执行Method(),当最后一个执行完毕后,

再通知原线程,最后显示完成提示。而不是调用一个Method()结束就输出结果。

个人觉得这应该是一个典型的“跨线程事件通知”问题,应该是ManualResetEvent的典型用法。
Feiin 2008-07-10
  • 打赏
  • 举报
回复
mark
pinhailinfeng 2008-07-10
  • 打赏
  • 举报
回复
学习.............
格拉 2008-07-10
  • 打赏
  • 举报
回复
学习!
wxm4585 2008-07-10
  • 打赏
  • 举报
回复
namespace ThreadCommunicate
{
public partial class Form1 : Form
{
public delegate void ThreadEventHandle();
public event ThreadEventHandle ThreadEvent;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
ThreadEvent += new ThreadEventHandle(Form1_ThreadEvent);
}

void Form1_ThreadEvent()
{
MessageBox.Show("thread ended");
}


private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(Method));
thread.Start();
}

private void Method()
{
Thread.Sleep(10000);
if (ThreadEvent != null)
ThreadEvent();

}

}
}
wxm4585 2008-07-10
  • 打赏
  • 举报
回复
又接着试了一下ManualResetEvent,发现也导致了主线程的挂起,不太理解为什么要这么处理,如果在等待副线程处理完成时挂起了主线程,那这样的多线程还有什么意义?
wxm4585 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 sb_CJ_sx 的回复:]
用Join和ManualResetEvent都可以实现,下面写了个简单的例子,假设用3个线程来完成
数据导入,其中方法StartTest1()和Method1()用Join实现功能,方法StartTest2()和
Method2()用ManualResetEvent实现功能.

class Program {
static ManualResetEvent m_Event = new ManualResetEvent(false);
static int m_EndedThreadCount = 0;

static void Main() {
Thread thread = new…
[/Quote]

Thread.Join的时候,主线程都挂起了,必须要等到三个副线程完成才能响应。用户体验很不好,
为啥不在副线程里面定义事件,主线程来订阅它,这种机制来实现通信?
sb_CJ_sx 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 jweet 的回复:]
每个线程都会执行MyMethod2 方法,那不是要调用三次m_Event.Set(); ,那么主线程中是否也会相应三次呢?
[/Quote]


调用m_Event.Set()表示m_Event状态为信号已发,从而释放等待线程。

m_Event的初始状态为信号未发,当三个线程都执行完毕即m_EndedThreadCount值为3时发信号。

方法m_Event.WaitOne()表示等待发信号。一旦接收到信号,该线程就会继续执行。

通常情况下m_Event.Set()仅在条件为真时执行一次,极端情况下可能调三次,但这并不影响正常运行。

因为第一次调用m_Event.Set()时,等待线程即恢复执行了,后面再调用实际没什么作用。
fuadam 2008-07-09
  • 打赏
  • 举报
回复
在你的异步委托里使用
ManualResetEvent e = new ManualResetEvent(false);
int num = //线程数
//... 几个线程进行操作
e.WaitOne();
//通知窗体




//每个线程在完成任务后进行判断,如果为了说明所有线程执行完毕
if (Interlocked.Decrement(ref num) == 0)
e.Set();
sb_CJ_sx 2008-07-09
  • 打赏
  • 举报
回复
用Join和ManualResetEvent都可以实现,下面写了个简单的例子,假设用3个线程来完成
数据导入,其中方法StartTest1()和Method1()用Join实现功能,方法StartTest2()和
Method2()用ManualResetEvent实现功能.

class Program {
static ManualResetEvent m_Event = new ManualResetEvent(false);
static int m_EndedThreadCount = 0;

static void Main() {
Thread thread = new Thread(StartTest1); //Use Join Test
thread.Start();
Thread.Sleep(3000);
thread = new Thread(StartTest2); //Use ManualResetEvent Test
thread.Start();
}

static void StartTest1() {
Thread[] myThreads = new Thread[3];
for (int i = 0; i < 3; ++i) {
myThreads[i] = new Thread(MyMethod1);
myThreads[i].Start();
}
for (int i = 0; i < 3; ++i) {
myThreads[i].Join(); //等待每个线程结束
}
Console.WriteLine("All threads ended.(Use Join)");
}

static void MyMethod1() {
//LoadData()
Thread.Sleep(1000);
}

static void StartTest2() {
Thread[] myThreads = new Thread[3];
for (int i = 0; i < 3; ++i) {
myThreads[i] = new Thread(MyMethod2);
myThreads[i].Start();
}
m_Event.WaitOne(); //等待每个线程结束
Console.WriteLine("All threads ended.(Use ManualResetEvent)");
}

static void MyMethod2() {
//LoadData()
Thread.Sleep(1000);
Interlocked.Increment(ref m_EndedThreadCount);
if (m_EndedThreadCount == 3)
m_Event.Set();
}
}

110,822

社区成员

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

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

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