惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Schneier on Security
Schneier on Security
N
Netflix TechBlog - Medium
IT之家
IT之家
MongoDB | Blog
MongoDB | Blog
博客园_首页
S
SegmentFault 最新的问题
H
Help Net Security
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
T
The Blog of Author Tim Ferriss
量子位
GbyAI
GbyAI
M
MIT News - Artificial intelligence
Recorded Future
Recorded Future
P
Privacy & Cybersecurity Law Blog
B
Blog
月光博客
月光博客
博客园 - 聂微东
Vercel News
Vercel News
罗磊的独立博客
腾讯CDC
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
A
Arctic Wolf
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
Blog — PlanetScale
Blog — PlanetScale
L
Lohrmann on Cybersecurity
I
Intezer
小众软件
小众软件
T
The Exploit Database - CXSecurity.com
Jina AI
Jina AI
C
Check Point Blog
AWS News Blog
AWS News Blog
C
Cisco Blogs
Martin Fowler
Martin Fowler
The Last Watchdog
The Last Watchdog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
宝玉的分享
宝玉的分享
S
Security Affairs
大猫的无限游戏
大猫的无限游戏
N
News and Events Feed by Topic
雷峰网
雷峰网
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
H
Hacker News: Front Page
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
F
Full Disclosure
P
Proofpoint News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Security Blog
Microsoft Security Blog

博客园 - iceboundrock

Introduction to the Reactive Extensions for JavaScript文章集合(收集贴) 美化VS2010在远程桌面/无法启动硬件加速渲染的机器下的字体显示 CCR源码分析-CCR架构 CCR源码分析-分析环境准备 CCR相关的Channel 9视频 DSS简介 也许你还不知道的一些关于App Domain的事 Common UNIX directories 几篇优化.net动态调用性能的文章 安装TFS 2008备注 Windbg点滴 MySQL Connector/Net 5.20安装后无法在VS2008中正常使用的问题 LAMP周边点滴 并行与并发编程学习心得 并发和协调运行时 其它并发方法 失败处理 迭代器 任务调度
与非CCR代码互操作
iceboundrock · 2007-12-17 · via 博客园 - iceboundrock

原文链接

线程套间约束

当与某些遗留的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, 01024);
            
// 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);
}