`
MagicBird
  • 浏览: 137438 次
  • 性别: Icon_minigender_2
  • 来自: 惠州
社区版块
存档分类
最新评论

ManualResetEvent用法 线程间操作无效: 从不是创建控件“XXX”的线程访问它

    博客分类:
  • c#
阅读更多

转之:http://blog.tom.com/blog/read.php?bloggerid=313638&blogid=13505http://hi.baidu.com/zsw_crown/blog/item/edba49123a32550f5baf53a6.html

ManualResetEvent用法

别相信别人告诉你的所有的事。其实C#中的线程是很简单的。
线程是程序中的控制流程的封装。你可能已经习惯于写单线程程序,也就是,程序在它们的代码中一次只在一条路中执行。如果你多弄几个线程的话,代码运行可能会更加“同步”。在一个有着多线程的典型进程中,零个或更多线程在同时运行。但是,在有着N个CPU的机器上,一个线程只能在给定的时间上在一个CPU上运行,因为每个线程都是一个代码段,每个CPU一次只能运行一段代码。而看起来像是N个同时完成是线程间共享CPU时间片的效果。这个例子里,我们将创建另一个线程,我们将用两个线程演示多线程的工作方式,最后,我们实现两个线程(主线程与新线程)同步,在新线程工作前必须等待消息。建立线程前我们必须引入System.Threading命名空间。然后我需要知道的是,线程得为控制流程建立一个起点。起点是一个函数,可以使一个相同的调用或其它。
这里你可以看到在同一个类中定义的起点函数。

using System;
using System.Threading;
namespace ThreadingTester
{
class ThreadClass
{
  public static void trmain()
  {
    for(int x=0;x < 10;x++)
    {
    Thread.Sleep(1000);
    Console.WriteLine(x);
    }
  }  
  static void Main(string[] args)
  {
    Thread thrd1=new Thread(new ThreadStart(trmain));
    thrd1.Start();
    for(int x=0;x < 10;x++) 
    {
    Thread.Sleep(900);
    Console.WriteLine("Main    :" + x);
    }
  }
}
}

 Thread.Sleep(n)方法把“this”线程置于n毫秒的休眠状态。你可以看看这个例子,在主函数我们定义了一个新的线程,其中它的起点是函数trmain(),我们然后包含了Start()方法开始执行。如果你运行这个例子,你就会了解线程间的切换(让CPU从运行一个线程转到另一个线程)让线程几乎同时运行,为了能看哪个线程运行更快我把主线程设置比新线程少100毫秒。
现在,在开始线程前,先给线程命名:
  Thread thrd1=new Thread(new ThreadStart(trmain));
  thrd1.Name="thread1";
  thrd1.Start();
  Thread tr = Thread.CurrentThread;
  Console.WriteLine(tr.Name);
在完成上面程序后,设想我们不想在一开始新线程就让它马上运行结束,也就是说,我们开启了一个新线程,让它运行,在某个特定的时间点,新线程暂停并等待从主线程(或其他线程)发来的消息。
我们可以这样定义:
  public static ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。注意,为了通知或监听同一个线程,所有的其它线程都能访问那个类。
等待线程这样写:
  mre.WaitOne();
这将引起等待线程无限期的阻塞并等待类来通知。
发信号的线程应该这样:
  mre.Set();
这样类就会被通知,值变成true,等待线程就会停止等待。在通知事件发生后,我们就可以使用下面语句把线程置于基状态:
  mre.Reset();
现在让我们在程序执行一下:

using System;
using System.Threading;
namespace ThreadingTester
{
class ThreadClass
{
public static ManualResetEvent mre=new ManualResetEvent(false);
public static void trmain()
{
Thread tr = Thread.CurrentThread;
Console.WriteLine("thread: waiting for an event");
mre.WaitOne();
Console.WriteLine("thread: got an event");
for(int x=0;x < 10;x++)
{
Thread.Sleep(1000);
Console.WriteLine(tr.Name +": " + x);
}
}  
static void Main(string[] args)

{
Thread thrd1=new Thread(new ThreadStart(trmain));
thrd1.Name="thread1";
thrd1.Start();
for(int x=0;x < 10;x++) 
{
Thread.Sleep(900);
Console.WriteLine("Main:" + x);
if(5==x) mre.Set();
}
while(thrd1.IsAlive)
{
Thread.Sleep(1000);
Console.WriteLine("Main: waiting for thread to stop");
}
}
}
}

 线程间操作无效: 从不是创建控件“XXX”的线程访问它

大家有没有注意到,但我们在一个控件的事件中启动一个线程的话:

 

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

private void Compute()
        {
            int value1 =int.Parse( textBox1.Text);
            int value2 = int.Parse(textBox2.Text);
            int value = value2 / value1;
            textBox2.Text = value.ToString();
        }

 

试试会有什么后果.呵呵 "线程间操作无效: 从不是创建控件“textBox2”的线程访问它。" 会出现这个错误的.

怎么办.

这时候就需要用到委托来进行处理.

先说下原理.因为控件处于UI线程.此时调用也处于此线程中.而此时里另一个线程却要赋值,就会造成线程间的混乱.因此.我要建造一个公共地方.让线程间共同使用.

public delegate void getCompute();

private void button1_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(new ThreadStart(StareNewThread));
            th.Start();
            //getCompute setdeleght = new getCompute(Compute);
            //setdeleght.Invoke();
            //this.BeginInvoke(new getCompute(Compute));
            
        }

private void StareNewThread()
        {
            getCompute Getdelegate = new getCompute(Compute);
            this.BeginInvoke(Getdelegate);
        }

private void Compute()
        {
            int value1 =int.Parse( textBox1.Text);
            int value2 = int.Parse(textBox2.Text);
            int value = value2 / value1;
            textBox2.Text = value.ToString();
        }

 

通过委托将函数作为参数传递。待续,以后觉得和线程有用的信息都记录于此,刚开始学习,希望大家一起进步。

分享到:
评论

相关推荐

    C#线程同步ManualResetEvent

    简单讲解ManualResetEvent用法,DEMO可以运行,简单易懂

    ManualResetEvent的用法

    ManualResetEvent的用法.日积月累

    C# ManualResetEvent使用方法详解

    本文实例为大家分享了ManualResetEvent的使用方法,供大家参考,具体内容如下 1. 源码下载: 下载地址:ManualResetEvent Demo: 2. ManualResetEvent详解  ManualResetEvent 允许线程通过发信号互相通信。通常,...

    C#-【多线程篇】AutoResetEvent和ManualResetEvent的区别(中级)

    引入命名空间: using System.Threading; AutoResetEvent: autoResetEvent.WaitOne();//运行完后,**自动将事件...ManualResetEvent: manulResetEvent.WaitOne();//运行完后,**不会自动将事件状态设置为无信号**

    ManualResetEvent继续等待.rar

    ManualResetEvent继续等待,ManualResetEvent超时后重置,VBNET源码,C#可用

    ManualResetEvent最简单的测试代码

    这是一个ManualResetEvent最简单的测试代码,用最简单的代码解释了ManualResetEvent的用法。

    C# ManualResetEvent用法详解

    主要介绍了C# ManualResetEvent用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    C#中ManualResetEvent用法详解

    当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态,此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止...

    NET多线程同步方法详解

    .NET多线程同步方法详解(一):... 除了以上的这些对象之外实现线程同步的还可以使用Thread.Join方法。这种方法比较简单,当你在第一个线程运行时想等待第二个线程执行结果,那么你可以让第二个线程Join进来就可以了。

    c#多线程学习入门经典

    C#多线程学习(一) 多线程的相关概念 什么是进程? 什么是线程? 什么是多线程? 多线程的好处 多线程的不利方面 线程操作的关键对象和语句 任何程序在执行时,至少有一个主线程。 Thread类有几个至关重要的方法 C#...

    C#多线程学习入门圣典

    线程操作的关键对象和语句 2 任何程序在执行时,至少有一个主线程。 2 Thread类有几个至关重要的方法 3 C#多线程学习(二) 如何操纵一个线程 3 Thread.ThreadState 属性 5 线程的优先级 5 C#多线程学习(三) 生产者和...

    vb.net C#线程锁超时控制代码

    ManualResetEvent是一个超时等待的线程锁,如果超时返回false,接收指令显示true,但是没法实现在超时后让他继续等待,这种需求我们可以用在以下场景: 控制线程超时方法 1.[主线程]:请求方发送请求,立即创建超时等待...

    C# 多线程同步与互斥,使用Mutex和AutoResetEvent类

    C# 使用Mutex和AutoResetEvent类处理多线程同步与互斥,调试并完善了网上文档的代码。经测试能很好地实现要求,但还有一些地方不是特别明白,都写在注释中了,请高手给予指点。

    AutoResetEvent_Examples.zip_AutoResetEvent_ManualResetEvent

    线程事例代码,ManualResetEvent,AutoResetEvent

    C#多线程学习入门圣典(修改版)

    (原Mutex 类的程序示例有点问题, 4个子线程获取到mutex后都没有执行ReleaseMutex()方法, 导致出现:由于出现被放弃的 mutex,等待过程结束 的异常, 这个是因为需要在获取mutex的线程里面执行ReleaseMutex()方法的, ...

    ManualResetEvent Timer组件 托管函数 委托加减 我的委托 AsyncCallback

    ManualResetEvent Timer组件 托管函数 委托加减 我的委托 AsyncCallback

    ManualResetEvent类的实例介绍

    ManualResetEven类的reset,waione,set方法的详细介绍,有多个实事例帮助理解

Global site tag (gtag.js) - Google Analytics