导读: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 = ;

    Dispatcher dispatcher = new Dispatcher(, "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 = ; i < maximumDepth * ; 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 = ; i < ; i++)

        {

            int k = i * i / ;

        }

    }

    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, , FileOptions.Asynchronous))

    {

        Byte[] data = new Byte[fs.Length];

        fs.BeginRead(data, , 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[];

        int bytesRead = -;

        // 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, , );

            // 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, , 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 > );

        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

与非CCR代码互操作的更多相关文章

  1. Java类加载信息的顺序:包括静态代码快、静态类变量、非静态代码快、构造方法、普通方法

    JVM运行之前会执行一个叫做类加载器的子系统,叫做ClassLoader,那么类里面那么多“元素”,究竟是个什么顺序呢,写几行代码测试一下,通过给每个方法和代码快和静态变量打上断点来测试: class ...

  2. ARC代码和非ARC代码 混用

    选中工程->TARGETS->相应的target然后选中右侧的“Build Phases”,向下就找到“Compile Sources”了.然后在相应的文件后面添加:-fobjc-arc参 ...

  3. java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数

    一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构

  4. 使用非java代码编程

    使用非JAVA代码     JAVA语言及其标准API(应用程序编程接口)应付应用程序的编写已绰绰有余.但在某些情况下,还是必须使用非JAVA编码.例如,我们有时要访问操作系统的专用特性,与特殊的硬件 ...

  5. Java静态代码块与非静态代码块

    静态代码块,格式是 static{ },随着类的加载而加载,且只执行一次. 在程序中,执行的优先级最高. 非静态代码块,格式是{ },在创建对象的时候运行(即new一个对象的时候),每创建一次对象就执 ...

  6. Java非静态代码块和静态代码块

    类中存在两种特殊的代码块,即非静态代码块和静态代码块,前者是直接由 { } 括起来的代码,而后者是由 static{ } 括起来的代码. 非静态代码块在类初始化创建实例时,将会被提取到类的构造器中执行 ...

  7. Java中静态变量、静态代码块、非静态代码块以及静态方法的加载顺序

    在研究单例设计模式的时候,用到了静态变量和静态方法的内容,出于兴趣,这里简单了解一下这四个模块在类初始化的时候的加载顺序. 经过研究发现,它们的加载顺序为: 1.非静态代码块 2.静态变量或者静态代码 ...

  8. 关于一致/非一致代码段与TSS 关系的个人看法

    [0]概念定义 0.1)一致代码段: 简单理解,就是操作系统拿出来被共享的代码段,可以被低特权级的用户直接调用访问的代码, 但是特权级高的程序不允许访问特权级低的数据. 通常这些共享代码,是" ...

  9. node总结--回调函数阻塞和非阻塞代码实例

    阻塞代码实例: var fs = require("fs"); var data = fs.readFileSync('input.txt'); console.log(data. ...

随机推荐

  1. 微软职位内部推荐-Sr SDE-MODC-Beijing

    微软近期Open的职位: JOB TITLE: Senior Software Design EngineerDEPARTMENT: Microsoft Office Division ChinaIM ...

  2. 1061: [Noi2008]志愿者招募 - BZOJ

    Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完 ...

  3. 破解之API断点法

    上回给大家做的破解教程,地址是http://www.52pojie.net/thread-52719-1-1.html,用的是“调用堆栈”方法.今天给新手提供另一种方法“API函数断点”,这种方法要求 ...

  4. linux服务器初步印象,远程连接mysql数据库,传输文件,启动/关闭tomcat命令

    1.连接服务器数据库,以Navicat连接mysql为例 1.1 常规 新建连接,连接名,主机名或ip地址:127.0.0.1 端口:3306用户名:(服务器端)root密码:(服务器端)pwd 1. ...

  5. jsp request.getParameterValues获取数组值代码示例

    tt.jsp <form action="tt2.jsp" method="POST"> <select name="two&quo ...

  6. xcode 把cocos2d-x 以源码的形式包含进自己的项目适合, 性能分析问题的错误

    性能分析:出现如下错误: xcode profile  Variable has incomplete type   class “CC_DLL” 解决办法:在 xcode的Build Setting ...

  7. Android:仿微信开场切换界面

    这实例很多人仿做,好实例还是不容错过!最重要是素材容易拿~ 效果: 默认3页面的切换,最后一个页面带按钮,点击进入另外一个页面 思路: 1.准备5个布局页面,1个为主函数布局页面,3个为切换的页面(其 ...

  8. 拔高你的Java代码质量吧:推荐使用枚举定义常量(转)

    提高你的Java代码质量吧:推荐使用枚举定义常量 一.分析 常量的声明是每一个项目中不可或缺的,在Java1.5之前,我们只有两种方式的声明:类常量和接口常量.不过,在1.5版之后有了改进,即新增了一 ...

  9. hadoop2.2.0安装

    64位编译和安装 http://blog.csdn.net/licongcong_0224/article/details/12972889 http://blog.csdn.net/w1377026 ...

  10. R语言学习笔记:怎么从txt中读入数据

    1   从该链接中下载测试数据,http://pan.baidu.com/share/link?shareid=3322971616&uk=3862050759   2   把测试文件Anal ...