• 异步调用模式学习记录


        异步调用一般有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的获取是在桌面线程中完成的,所以也就不成在冲突了!!!

  • 相关阅读:
    解决Cell重绘导致 重复的问题
    给Cell间隔颜色
    NSUserDefault 保存自定义对象
    xcode6 下载
    unrecognized selector sent to instance
    16进制颜色转换
    local unversioned, incoming add upon update问题
    应用崩溃邮件通知
    TabBar变透明
    代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧
  • 原文地址:https://www.cnblogs.com/pojia/p/315454.html
Copyright © 2020-2023  润新知