与非CCR代码互操作

导读:CCR可以轻松的承载STA组件或者与它互操作:组件应该创建一个只有一个线程的CCR Dispatcher实例,并且在Dispatcher的构造函数中指定线程套间策略。DispatcherQueue实例就可以在与需要和遗留代码交互 的地方使用这个dispatcher来激活处理函数(activating handlers)。这些处理函数就可以安全的访问COM或者WinForm对象,同时对其他的CCR组件隐藏它们的STA关系,以便其他CCR组件可以 简单的投递元素到常规的CCR ports而不需要关心port上的处理函数使用的是什么dispatcher。

原文链接

线程套间约束

当与某些遗留的Windows组件,特别是COM对象交互时需要特定的线程套件策略。甚至最近的框架,例如.net WinForms,也需要在运行WinForm的线程上应用单线程套间(SingleThreadedApartment)策略。

CCR可以轻松的承载STA组件或者与它互操作:组件应该创建一个只有一个线程的CCR Dispatcher实例,并且在Dispatcher的构造函数中指定线程套间策略。DispatcherQueue实例就可以在与需要和遗留代码交 互的地方使用这个dispatcher来激活处理函数(activating handlers)。这些处理函数就可以安全的访问COM或者WinForm对象,同时对其他的CCR组件隐藏它们的STA关系,以便其他CCR组件可以 简单的投递元素到常规的CCR ports而不需要关心port上的处理函数使用的是什么dispatcher。

CCR WinFrom适配库(Ccr.Adapters.Winforms.dll)是一个在CCR中运行.net WinForm的便利方法。

与应用的主线程协调

CCR软件组件经常在一个CLR应用的上下文中中执行,例如一个独立执行程序。.net运行时使用一个操作系统 线程启动一个程序,当线程退出时终止程序。由于CCR应用是异步、并发的,所以它们在没有消息被发送时处于非激活状态,并且几乎不会阻塞任何线程。CCR Dispatcher将保持线程在一种高效的休眠状态,但是如果其它的线程被作为后台线程创建,应用程序将会退出,那么CCR还在执行。

一个与CLR启动的同步世界接口的常见模式是使用System.Threading.AutoResetEvent来阻塞应用的主线程,直到CCR应用完成。AutoResetEvent事件可以被任何CCR处理函数触发。

例25.

复制代码
void  InteropBlockingExample()
{
    
//  create OS event used for signalling
    AutoResetEvent signal  =   new  AutoResetEvent( false );

    
//  schedule a CCR task that will execute in parallel with the rest of
    
//  this method
    Arbiter.Activate(
        _taskQueue,
        
new  Task < AutoResetEvent > (signal, SomeTask)
    );
    
//  block main application thread form exiting
    signal.WaitOne();
}

void  ThrottlingExample()
{
    
int  maximumDepth  =   10 ;
    Dispatcher dispatcher 
=   new  Dispatcher( 0 " throttling example " );
    DispatcherQueue depthThrottledQueue 
=   new  DispatcherQueue( " ConstrainQueueDepthDiscard " ,
          dispatcher,
          TaskExecutionPolicy.ConstrainQueueDepthDiscardTasks,
          maximumDepth);

    Port
< int >  intPort  =   new  Port < int > ();
    Arbiter.Activate(depthThrottledQueue,
       Arbiter.Receive(
true , intPort,
       
delegate ( int  i)
       {
           
//  only some items will be received since throttling will discard most of them
           Console.WriteLine(i);
       })
    );

    
//  post items as fast as possible so that the depth policy is activated and discards
    
//  all the oldest items in the dispatcher queue
     for  ( int  i  =   0 ; i  <  maximumDepth  *   100000 ; i ++ )
    {
        intPort.Post(i);
    }
}



///   <summary>
///  Handler that executes in parallel with main application thread
///   </summary>
///   <param name="signal"></param>
void  SomeTask(AutoResetEvent signal)
{
    
try
    {
        
for  ( int  i  =   0 ; i  <   1000000 ; i ++ )
        {
            
int  k  =  i  *  i  /   10 ;
        }
    }
    
finally
    {
        
//  done, signal main application thread
        signal.Set();
    }
}
复制代码
在上面的例子中,我们演示了一个使用操作系统事件来阻塞应用程序主线程的小例子。

简化.NET异步编程模式

CCR可以用于任何实现了异步变成模型模式的.net类型。它实际上极大的简化了异步模式,并且当用于C#时,完全不再需要delegate和接续传递(continuation passing)。CCR迭带器调度支持允许你直接返回并继续(yield)挂起的I/O操作并且实现的易读的代码和过去只能在同步代码中实现的模式。

例27.

 

复制代码
IEnumerator < ITask >  CcrReadEnumerator( string  filename)
{
    var resultPort 
=   new  Port < IAsyncResult > ();
    
//  stage 1: open file and start the asynchronous operation
     using  (FileStream fs  =   new  FileStream(filename, 
        FileMode.Open, FileAccess.Read, FileShare.Read, 
8192 , FileOptions.Asynchronous))
    {
        Byte[] data 
=   new  Byte[fs.Length];
        fs.BeginRead(data, 
0 , data.Length, resultPort.Post,  null );    
        
//  stage 2: suspend execution until operation is complete
         yield   return  Arbiter.Receive( false , resultPort,  delegate  { });
        
//  stage 3: retrieve result of operation just by assigned variable to CCR port
        var ar  =  (IAsyncResult)resultPort;
        
try
        {   Int32 bytesRead 
=  fs.EndRead(ar); }
        
catch
        {   
            
//  handle I/O exception 
        }
        ProcessData(data);
    }
}
复制代码
例子27演示了CCR如何使用文件流的异步编程模型BeginRead/EndRead方法而又不需要传递delegate。取而代之的是,我们提供一个CCR Port的Post方法,所以异步结果被直接投递到一个CCR Port。 代码返回并继续在一个port上进行接受 操作。yield return语句允许我们编写逻辑上顺序的 代码而不需要使用一个 操作系统线程。 代码保留了异步的可伸缩性和overlapped 操作,但是读起来就像是同步、顺序的 代码

例28
复制代码
///   <summary>
///  Read from one stream into a Http request stream, asynchronously
///   </summary>
public   virtual  IEnumerator < ITask >  UploadHttpStream( string  contentUrl,
    Stream contentStream, PortSet
< HttpStatusCode, Exception >  resultPort)
{
    
//  Create HTTP request
    HttpWebRequest webRequest  =  (HttpWebRequest)WebRequest.Create(contentUrl);
    webRequest.Method 
=   " POST " ;
    HttpStatusCode status 
=  HttpStatusCode.OK;
    Exception ex 
=   null ;
    
using  (Stream requestStream  =  webRequest.GetRequestStream())
    {
        
byte [] readBuffer  =   new   byte [ 1024 ];
        
int  bytesRead  =   - 1 ;
        
//  With CCR and iterators you can do loops and asynchronous I/O
         do
        {
            
//  use CCR stream adapter (or a custom APM adapter) to schedule operation
            var ioResultPort  =  StreamAdapter.Read(contentStream, readBuffer,  0 1024 );
            
//  yield to result (success or failure)
             yield   return  (Choice)ioResultPort;
            
//  check for error
            ex  =  ioResultPort;
            
if  (ex  !=   null )
            {
                resultPort.Post(ex);
                
//  exit on error
                 yield   break ;
            }
            bytesRead 
=  ioResultPort;
            var writeResultPort 
=  StreamAdapter.Write(requestStream, readBuffer,  0 , bytesRead);
            
//  yield to write operation
             yield   return  (Choice)writeResultPort;
            
//  check for write error
            ex  =  writeResultPort;
            
if  (ex  !=   null )
            {
                resultPort.Post(ex);
                
yield   break ;
            }
        } 
while  (bytesRead  >   0 );

        requestStream.Flush();
    }
    
//  Use built-in CCR adapter for reading HTTP response
    var webResultPort  =  WebRequestAdapter.ReadResponse(webRequest, _taskQueue);
    
//  yield to web response operation
     yield   return  (Choice)webResultPort;
    
//  check for any exceptions
    GetErrorDetails((Exception)webResultPort,  out  status);
    resultPort.Post(status);
}
复制代码
例子28展示了一个更复杂的异步变成模型交互:一个CCR迭带器被调度来从一个流异步的读取数据,然后再异步的把数据写到一个HTTP请求流中。值得注意的是,CCR可以表达内部包含异步 操作的while和for循环。

参考

MSDN Magazine: Concurrent Affairs -- Concurrency and Coordination Runtime

转载于:https://www.cnblogs.com/zeroone/p/3285902.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值