博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
与非CCR代码互操作
阅读量:6250 次
发布时间:2019-06-22

本文共 5446 字,大约阅读时间需要 18 分钟。

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

转载地址:http://qeusa.baihongyu.com/

你可能感兴趣的文章
Oracle之比较NVARCHAR2字符串
查看>>
linux系统常用命令
查看>>
用原始方法解析复杂字符串,json一定要用JsonMapper么?
查看>>
Linux ld命令
查看>>
在 Word 中的受支持的区域设置标识符的列表
查看>>
No package的问题解决
查看>>
【转】chrome浏览器的跨域设置——包括版本49前后两种设置
查看>>
母牛的故事
查看>>
Caffe + Ubuntu 14.04 64bit + CUDA 6.5 配置说明2
查看>>
javaScript基础练习题-下拉框制作
查看>>
基于 OAuth 安全协议的 Java 应用编程1
查看>>
使用Golang利用ectd实现一个分布式锁
查看>>
javaweb学习总结五(内省、beanUtils工具包)
查看>>
An easy to use android color picker library
查看>>
iOS10全新推送功能的实现
查看>>
C#中容易被忽视的细节整理
查看>>
php内核分析(二)-ZTS和zend_try
查看>>
获取form对象
查看>>
不确定人数的抽奖方法
查看>>
win7 windows server 2008R2下 https SSL证书安装的搭配(搭配https ssl本地测试环境)
查看>>