关于ManualResetEvent 阻止线程

Sq-Zyz123 2014-12-25 10:12:41
 ManualResetEvent resumeEvent = new ManualResetEvent(false);
volatile bool paused;
/// <summary>
/// 阻止线程
/// </summary>
void pause()
{
resumeEvent.Reset();
paused = true;
}
/// <summary>
/// 继续线程
/// </summary>
void Resume()
{
paused = false;
resumeEvent.Set();
}
public void MendthCall(string[] args, int index)
{
string str1 = "";
//获取服务器配置信息
List<string> list = GetSeverConfig();
//服务器调用方法
RemotingServerConn conn = new RemotingServerConn();


for (int i = 0; i < list.Count; i++)
{

//连接服务器
ExecuteCOM ec = conn.ServerConn(list[i]);
str1 = IsLeisureServer(ec);//查找到空闲状态任务的句柄
if (str1 != null && str1.Trim() != "")
{
break;
}
}
if (str1 == "")
{

resumeEvent.WaitOne();
//pause();
}
try
{
for (int i = 0; i < list.Count; i++)
{
//连接服务器
ExecuteCOM ec = conn.ServerConn(list[i]);
string str = IsLeisureServer(ec);//查找到空闲状态任务的句柄
if (str != null && str.Trim() != "")
{
_ICOMcallback = new ICOMCallBack();
_ICOMcallback.OnExecuteComplete_Event += new ExecuteComplete_Event(ExecuteComplete_EventMethod);
ec.AddOnlineCallBack(_ICOMcallback);
if (index != -1)
{
args[index] = str;
}
ec.ExecuteAsyncPreAndCal(args, index);
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "错误提示");
}
}
/// <summary>
/// 获取返回结果
/// </summary>
/// <param name="str"></param>
void ExecuteComplete_EventMethod(string str)
{
if (EventRemotingArgs != null)
{
//if (paused)
//{
//Resume();
resumeEvent.Set();
resumeEvent.Reset();
//}
RemotingResult result = new RemotingResult();
result.result = str;
EventRemotingArgs(this, result);
}
}

我想在接收事件哪里给ManualResetEvent set() 但是set执行完了,阻止的线程并没有执行、我这么写就没问题,下面这个例子没问题,但是上面这个例子就是执行了set() 但是WaitOne()阻止在哪的线程缺没动静。- -

      bool bol = false;
ManualResetEvent manual = new ManualResetEvent(false);
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(new ThreadStart(ss));
th.Start();

textBox1.Text += "qwe";

}

void ss()
{
//Thread.Sleep(3000);
this.Invoke(new MethodInvoker(delegate() { textBox1.Text += "123243"; }));
manual.WaitOne();
Thread.Sleep(3000);
this.Invoke(new MethodInvoker(delegate() { textBox1.Text += "456"; }));
}

private void button2_Click(object sender, EventArgs e)
{
manual.Set();
manual.Reset();

}
...全文
200 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
於黾 2014-12-25
  • 打赏
  • 举报
回复
manual.WaitOne(); manual.Reset(); 这样 不要在set之后马上reset
於黾 2014-12-25
  • 打赏
  • 举报
回复
因为CPU调度线程是轮询的方式,并不是你在一个线程里设置set,另一个线程就马上能得到执行 你可以想象成自己定义个bool变量,如果判断它为false,就while,sleep 你立即将它设置成false,那么当线程要执行的时候,它依然是false,检测不到它曾经变成true过 当然.net封装好的ResetEvent比你自己while判断效率高,因为如果是false,CPU根本不执行线程,而不是先执行了线程,再重新进入sleep状态
Sq-Zyz123 2014-12-25
  • 打赏
  • 举报
回复
引用 6 楼 Z65443344 的回复:
哦,那是我记反了,false是第一次阻塞,true是第一次不阻塞 你试试不要在manual.Set();之后马上执行manual.Reset(); 把manual.Reset();放到线程里,执行完代码设置成false 或者使用AutoResetEvent,就不用你管到底该什么时候reset了
AutoResetEvent我也试了,不行。。
Sq-Zyz123 2014-12-25
  • 打赏
  • 举报
回复
引用 4 楼 Z65443344 的回复:
还有 如果你使用AutoResetEvent 就不需要手动执行manual.Reset();了 它会自动复位
现在问题是我阻塞完了之后,在接收事件里面set了但是被阻塞的语句并没有执行,很纳闷,这也只是俩个线程啊,跟第二例子应该是一样的吧?
於黾 2014-12-25
  • 打赏
  • 举报
回复
哦,那是我记反了,false是第一次阻塞,true是第一次不阻塞 你试试不要在manual.Set();之后马上执行manual.Reset(); 把manual.Reset();放到线程里,执行完代码设置成false 或者使用AutoResetEvent,就不用你管到底该什么时候reset了
Sq-Zyz123 2014-12-25
  • 打赏
  • 举报
回复
引用 3 楼 Z65443344 的回复:
ManualResetEvent manual = new ManualResetEvent(false); 改成 ManualResetEvent manual = new ManualResetEvent(true); 试试 这个参数是第一次执行是否阻塞
不行改成true直接不阻塞了,直接继续下一条语句了。
於黾 2014-12-25
  • 打赏
  • 举报
回复
还有 如果你使用AutoResetEvent 就不需要手动执行manual.Reset();了 它会自动复位
於黾 2014-12-25
  • 打赏
  • 举报
回复
ManualResetEvent manual = new ManualResetEvent(false); 改成 ManualResetEvent manual = new ManualResetEvent(true); 试试 这个参数是第一次执行是否阻塞
Sq-Zyz123 2014-12-25
  • 打赏
  • 举报
回复
谁来帮帮忙给讲解下啊。。这个相当于第一个线程接收到返回消息,就启动阻塞的线程,可是为什么没反应啊?
Sq-Zyz123 2014-12-25
  • 打赏
  • 举报
回复
最上面的那个代码差一个调用
        public void aaa(string[] args, int index)
        {
           t = new Thread(delegate() { MendthCall(args, index); });
           t.Start();
          
        }
於黾 2014-12-25
  • 打赏
  • 举报
回复
如果你的resumeEvent.WaitOne();只执行一次 那么其他地方不管多少个地方执行set和reset都没啥意义,因为根本不会再次阻塞在这一句
於黾 2014-12-25
  • 打赏
  • 举报
回复
所以说,你这个resumeEvent.WaitOne();放的位置就很让人费解了 你这相当于线程一开始,就等着,直到按钮按下,才能继续执行,而且一执行就不会再停下来
於黾 2014-12-25
  • 打赏
  • 举报
回复
_ICOMcallback.OnExecuteComplete_Event += new ExecuteComplete_Event(ExecuteComplete_EventMethod); 你在try里注册的回调函数 也就是说,如果不执行try,你根本接收不到任何东西
Sq-Zyz123 2014-12-25
  • 打赏
  • 举报
回复
引用 14 楼 Z65443344 的回复:
你不会以为使用了WaitOne(); 把它放在代码的任何地方,只要reset整个线程都会停止吧? 线程只会停在WaitOne();这一条语句上
下面的那个例子已经是通过的,可以等待执行,上面的不行,是没放在循环里面啊,但是我在事件接收哪里set()了之后,阻塞的那边应该会执行循环下try下的语句吧?
於黾 2014-12-25
  • 打赏
  • 举报
回复
你不会以为使用了WaitOne(); 把它放在代码的任何地方,只要reset整个线程都会停止吧? 线程只会停在WaitOne();这一条语句上
於黾 2014-12-25
  • 打赏
  • 举报
回复
再说了 resumeEvent.WaitOne(); 你根本没有放到for循环里面啊 这不是一下就走过去了,你再点停止还是继续,代码都已经走完了
於黾 2014-12-25
  • 打赏
  • 举报
回复
Thread th = new Thread(new ThreadStart(ss)); th.Start(); 多线程不就一句话吗,有什么毛病 你到底是拿下面的测试代码测试的,还是直接放到你上面的真实代码里测试去了?? 先用测试代码测试好了到底怎么用,再想办法改造你上面的代码.否则只会越改越乱套
Sq-Zyz123 2014-12-25
  • 打赏
  • 举报
回复
引用 10 楼 Z65443344 的回复:
manual.WaitOne(); manual.Reset(); 这样 不要在set之后马上reset
不行,跟这个没关系,reset()是重置状态,总感觉我多线程写的有毛病。- -。。

110,561

社区成员

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

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

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