zoukankan      html  css  js  c++  java
  • 异步调用模式学习记录

        异步调用一般有BeginXXX和EndXXX这两种方法,开始调用BeginXXX方法时候,程序会立即响应,并抛出一线程,使当前线程继续
    下去。在这里我为了简单,使用桌面线程为主线程,由她抛出一个子线程。在抛出之后,就会有两线程分享CPU时间片。
       什么时候知道异步完成了?这里就需要提到BeginXXX方法会返回的一个IAsyncResult对象,此对象跟踪异步调用的过程,提供状态信息,关于此点可以参考:http://www.microsoft.com/china/MSDN/library/archives/library/dnnetCOMp/html/netcfWebServices.asp#netcfwebservices_topic2

       现在重要说一下,BeginXXX方法传递一个回调委托,然后通过EndXXX响应的过程;有事例如下:

    localhost.Service1 service=new localhost.Service1();  ///创建代理类
    DataGrid dg;
    private void SomeUIEvent( object sender, EventArgs e )
    {
       // Create a callback delegate so we will
         
        AsyncCallback callBack = new
          AsyncCallback( DataCallback );

       // Start retrieving the customer data.
       service.BeginGetData( "User", callBack,  service);
    }

    public void DataCallback( IAsyncResult ar )
    {
          // Retrieve the customer data.
          localhost.Service1 service=(localhost.Service1)ar.AsyncState;
          DataSet ds1 = service.EndGetData( ar );
         dg.DataSource=ds1;//注意
    }

      
     在这里就完成异步,取的数据,,但是如果仔细看,,ds这个在桌面线程中创建的DataSet,可能被多个子线程同时使用,如果在某一线程对DataSe做出修改的同时,其它线程也去使用它,那么最后结果就不好断定,反正不是自己想要的!!
    怎么解决这个问题,,我找到两种方法,一是使用线程的临界区,也就是使用lock,将要操作DataSet的代码区保护起来,保证每次只有一个线程进入此临界区,例如:
    public void CustomerDataCallback( IAsyncResult ar )
    {
      lock(this){
          // Retrieve the customer data.
          localhost.Service1 service=(localhost.Service1)ar.AsyncState;
          DataSet ds1 = service.EndGetData( ar );
          dg.DataSource=ds1;
       }
    }
    这里需要注意的,所有要使用dg的地方都要用lock,,,
    这样好象就很麻烦!!!

    另外一种是使用Control.Invoke方法,以实现线程的安全切换,比如:
    public void DataCallback( IAsyncResult ar )
    {
          // Retrieve the customer data.
          localhost.Service1 service=(localhost.Service1)ar.AsyncState;
          DataSet ds1 = service.EndGetData( ar );

          // Create an EventHandler delegate.
          EventHandler updateUI = new EventHandler( UpdateUI );

          // Invoke the delegate on the UI thread.
          this.Invoke( updateUI, new object[] { ds1, null } );
    }

    private void UpdateUI( object sender, EventArgs e )
    {
          // Update the user interface.
          dg.DataSource = (DataSet)sender;
    }


    最后你可以把Console.WriteLine("thread {0} does some work.",
        AppDomain.GetCurrentThreadId());
    放入以上方法中,,你会发现桌面线程和 UpdateUI所在的线程是一样的!!!!也就是说ds的获取是在桌面线程中完成的,所以也就不成在冲突了!!!

  • 相关阅读:
    leetcode Lowest Common Ancestor of a Binary Tree
    leetcode 141、Linked list cycle
    leetcode 136、Single Number
    tensorflow使用
    c++ priority_queue
    python语法
    CSS基础之选择器
    并发编程的一些理解
    封装的绑定与多态
    继承与派生
  • 原文地址:https://www.cnblogs.com/pojia/p/315454.html
Copyright © 2011-2022 走看看