C# 多线程的问题

1.invoke的功能,用法有些。

 invoke 主要是处理多线程,在多线程中主要的有线程同步。

参照以下文档:

1.使用IAsyncResult asyncResult属性来判断异步调用是否完成

 

WaitOne的第一个参数表示要等待的毫秒数,在指定时间之内,WaitOne方法将一直等待,直到异步调用完成,并发出通知,WaitOne方法才返回true。当等待指定时间之后,异步调用仍未完成,WaitOne方法返回false,如果指定时间为0,表示不等待,如果为-1,表示永远等待,直到异步调用完成。

 

static void Main(string[] args)
 {

     NewTaskDelegate task = newTask;
    IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
   while (!asyncRe ==sult.IsCompleted)
     {

          Console.Write("*"); Thread.Sleep(100); } // 由于异步调用已经完成,因此, EndInvoke会立刻返回结果
         int result = task.EndInvoke(asyncResult);
    Console.WriteLine(result);
 }  

 

2.使用WaitOne方法等待异步方法执行完成
static void Main(string[] args)

{

        NewTaskDelegate task = newTask;

        IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);

         while (!asyncResult.AsyncWaitHandle.WaitOne(100, false))

         {

            Console.Write("*");

         }

          int result = task.EndInvoke(asyncResult); Console.WriteLine(result);

 }

 3、使用回调方式返回结果    

 

 上面介绍的几种方法实际上只相当于一种方法。这些方法虽然可以成功返回结果,也可以给用户一些提示,但在这个过程中,整个程序就象死了一样(如果读者在GUI程序中使用这些方法就会非常明显),要想在调用的过程中,程序仍然可以正常做其它的工作,就必须使用异步调用的方式。下面我们使用GUI程序来编写一个例子,代码如下:
private delegate int MyMethod();

private int method()

{

       Thread.Sleep(10000);

        return 100;

}

 private void MethodCompleted(IAsyncResult asyncResult)

 {

     if (asyncResult == null)

          return;

     textBox1.Text = (asyncResult.AsyncState as MyMethod).EndInvoke(asyncResult).ToString();

 }

 private void button1_Click(object sender, EventArgs e)

{  

   MyMethod my = method;

   IAsyncResult asyncResult = my.BeginInvoke(MethodCompleted, my);

 }
    要注意的是,这里使用了BeginInvoke方法的最后两个参数(如果被调用的方法含有参数的话,这些参数将作为BeginInvoke的前面一部分参数,如果没有参数,BeginInvoke就只有两个参数了)。第一个参数是回调方法委托类型,这个委托只有一个参数,就是IAsyncResult,如MethodCompleted方法所示。当method方法执行完后,系统会自动调用MethodCompleted方法。BeginInvoke的第二个参数需要向MethodCompleted方法中传递一些值,一般可以传递被调用方法的委托,如上面代码中的my。这个值可以使用IAsyncResult.AsyncState属性获得。

    由于上面的代码通过异步的方式访问的form上的一个textbox,因此,需要按ctrl+f5运行程序(不能直接按F5运行程序,否则无法在其他线程中访问这个textbox,关于如果在其他线程中访问GUI组件,并在后面的部分详细介绍)。并在form上放一些其他的可视控件,然在点击button1后,其它的控件仍然可以使用,就象什么事都没有发生过一样,在10秒后,在textbox1中将输出100。

  

 

 作者:佚名  http://www.diybl.com/course/4_webprogram/asp.net/netjs/2008714/133128.html

 


   using System;
   using System.Runtime.Remoting.Messaging;
   using System.Threading;
  namespace 等待句柄
  {
  //委托声明(函数签名)
  delegate string MyMethodDelegate();
  class MyClass
  {
   //要调用方法1
   public string Write1()
   {
   for(double i = 0; i < 100000000000;i++)

   Console.WriteLine("执行方法1");
   return "";
   }
   //要调用方法2
   public string Write2()
   {
   Console.WriteLine("执行方法2");
   return "22222222222222";
   }
   //要调用方法3
   public string Write3()
   {
   Console.WriteLine("执行方法3");
   return "33333333333333";
   }
   [STAThread]
   static void Main(string[] args)
   {
   MyClass myClass = new MyClass();
   MyMethodDelegate d1 = new MyMethodDelegate(myClass.Write1);
   MyMethodDelegate d2 = new MyMethodDelegate(myClass.Write2);
   MyMethodDelegate d3 = new MyMethodDelegate(myClass.Write3);
   AsyncResult myResult1,myResult2,myResult3; //此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
   myResult1 = (AsyncResult)d1.BeginInvoke(null,null); //调用
  
   myResult2 = (AsyncResult)d2.BeginInvoke(null,null);
  
   myResult3 = (AsyncResult)d3.BeginInvoke(null,null);
   //建立WaitHandle数组对象
   WaitHandle[] waitHandle = new WaitHandle[3]{myResult1.AsyncWaitHandle,myResult2.AsyncWaitHandle,myResult3.AsyncWaitHandle};
  /*
   try
   {
   //等待三个异步方法中的至少一个执行完成,才继续执行下面的语句
   WaitHandle.WaitAny(waitHandle);
   }
   catch(Exception ex)
   {
   throw new Exception(ex.Message);
   }
  */
   myResult1.AsyncWaitHandle.WaitOne(); //如果当前异步方法还没有完成,此异步方法执行完毕才往下执行
   myResult2.AsyncWaitHandle.WaitOne();
   myResult3.AsyncWaitHandle.WaitOne();
  /*
   myResult1.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1),false); //如果当前异步方法还没有完成,则等待一秒的时间执行此方法; 如果一秒后此方法还未完成的话,则不再等待,继续往下执行
   myResult2.AsyncWaitHandle.WaitOne();
   myResult3.AsyncWaitHandle.WaitOne();
  */
  
   Console.WriteLine("测试等待句柄"); //标记语句用.
   Console.Read();
   }
  }
  }
  本示例代码已经测试,能够正常运行!
http://www.wangchao.net.cn/bbsdetail_74766.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在多线程编程中,资源共享是一个常见的问题。当多个线程同时访问和修改共享资源时,如果没有正确的同步机制,就会出现数据竞争和不可预测的结果。以下是一些处理多线程资源共享问题的常用方法: 1. 使用互斥锁(Mutex)或锁(lock):通过在访问共享资源的代码块上加锁,确保同一时间只有一个线程可以访问该资源。这样可以避免数据竞争和并发修改的问题。 ```csharp private static readonly object lockObject = new object(); lock (lockObject) { // 访问共享资源的代码 } ``` 2. 使用线程安全的集合类:在C#中,有一些线程安全的集合类,例如`ConcurrentQueue`、`ConcurrentStack`、`ConcurrentDictionary`等。它们内部实现了适当的同步机制,可以在多线程环境下安全地进行读写操作。 ```csharp ConcurrentQueue<int> queue = new ConcurrentQueue<int>(); // 线程1往队列中添加元素 queue.Enqueue(1); // 线程2从队列中取出元素 int item; if (queue.TryDequeue(out item)) { // 处理取出的元素 } ``` 3. 使用互斥体(Monitor):通过使用`Monitor`类来创建临界区,确保只有一个线程可以进入临界区访问共享资源。 ```csharp private static readonly object lockObject = new object(); Monitor.Enter(lockObject); try { // 访问共享资源的代码 } finally { Monitor.Exit(lockObject); } ``` 4. 使用原子操作:C#提供了一些原子操作的方法,例如`Interlocked`类的方法,可以在多线程环境下进行原子性的读写操作,避免数据竞争和并发修改的问题。 ```csharp private static int counter = 0; Interlocked.Increment(ref counter); // 原子性地增加计数器 ``` 以上方法可以帮助你处理多线程资源共享问题,确保线程安全和数据一致性。根据具体情况选择合适的方法来处理资源共享,以满足程序的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值