Excel的线程 与 SynchronizationContext的实现
COM组件的线程模型与Excel多线程的背景知识
COM组件的线程模型被称之为Apartment模型,COM对象初始化时其执行上下文(Execution Context),他要么和单个线程关联STA(Single Thread Apartment ) 要么和多个线程关联MTA(Multi Thread Apartment)。Excel是一种STA线程的应用程序,使用多线程直接怼会出问题,必须借助线程的同步上下文实现线程间的消息传递。
1、Excel 开发中与线程相关的若干问题参考这个链接:
2、SynchronizationContext的实现参考这个链接(共3篇文章,进入链接后可以找到下一章的链接):
https://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I
3、ExcelDNA是什么
Excel-DNA is an independent project to integrate .NET into Excel. With Excel-DNA you can make native (.xll) add-ins for Excel using C#, Visual Basic.NET or F#, providing high-performance user-defined functions (UDFs), custom ribbon interfaces and more. Your entire add-in can be packed into a single .xll file requiring no installation or registration.
4、ExcelDNA下实现一个自定义的SynchronizationContext
https://groups.google.com/forum/#!searchin/exceldna/synchronizationcontext%7Csort:date/exceldna/pyybn0lSP8k/3DW6NOekCgAJ
ExcelDNA中的解决方案
dynamic app;
dynamic worksheet; public void Test(IRibbonControl ribbonControl)
{
app = ExcelDnaUtil.Application;
worksheet = app.ActiveSheet;
worksheet.Cells[, ].Value = Thread.CurrentThread.ManagedThreadId;
Action<object> action = Run;
Task task = new Task(action,ExcelSynchronizationContext.Current);
task.Start(); }
private void Run(object context)
{
worksheet.Cells[, ].Value = Thread.CurrentThread.ManagedThreadId; for (int i = ; i < ; i++)
{
Thread.Sleep();
ExcelAsyncUtil.QueueAsMacro(UpdateUI, i);
}
} private void UpdateUI(object state)
{
int i = (int)state + ;
worksheet.Cells[i, ].Value = i;
worksheet.Cells[i, ].Value = Thread.CurrentThread.ManagedThreadId;
}
Task task = new Task(action,ExcelSynchronizationContext.Current); ExcelSynchronizationContext.Current为主线程的SynchronizationContext。
ExcelAsyncUtil.QueueAsMacro(UpdateUI, i); 其实是执行了SynchronizationContext的Post方法。 上面是ExcelDNA里集成的SynchronizationContext实现,有兴趣可以→ 尝试实现自定义一个SynchronizationContext
一个SendOrPostCallbackItem实例为一组SendOrPostCallback委托与方法、参数
internal enum ExecutionType
{
Post,
Send
}
internal class SendOrPostCallbackItem
{
object state;
ExecutionType executionType;
SendOrPostCallback callbackMethod; internal SendOrPostCallbackItem(SendOrPostCallback callback, object state, ExecutionType executionType)
{
this.callbackMethod = callback;
this.state = state;
this.executionType = executionType;
} internal void Execute()
{
if (executionType == ExecutionType.Post)
Post();
else
Send();
}
internal void Send()
{
throw new NotImplementedException();
} internal void Post()
{
callbackMethod(state);
}
}
DiyExcelSynchronizationContext,在ExcelDNA下实现一个SynchronizationContext
public class DiyExcelSynchronizationContext : SynchronizationContext
{
private const string RunMacroName = "ExcelSyncContext.Run";
private static readonly ConcurrentQueue<SendOrPostCallbackItem> queue = new
ConcurrentQueue<SendOrPostCallbackItem>();
private static readonly TimeSpan BackoffTime = TimeSpan.FromSeconds();
[ExcelCommand(Name = RunMacroName)]
public static void Run()
{
while (true)
{
SendOrPostCallbackItem workItem;
if (!queue.TryDequeue(out workItem))
{
return;
}
workItem.Execute();
}
}
dynamic application = ExcelDnaUtil.Application;
public override void Post(SendOrPostCallback d, object state)
{ SendOrPostCallbackItem item = new SendOrPostCallbackItem(d, state, ExecutionType.Post);
queue.Enqueue(item);
Task.Factory.StartNew(() =>
{
while (true)
{
try
{
application.Run(RunMacroName);
break;
}
catch (COMException e1)
{
if (IsRetry(e1))
{
Thread.Sleep(BackoffTime);
continue;
}
return;
}
catch (Exception e2)
{
return;
}
} });
}
public const uint RPC_E_SERVERCALL_RETRYLATER = 0x8001010A;
public const uint RPC_E_CANTCALLOUT_INASYNCCALL = 0x800AC472; public static bool IsRetry(COMException e)
{
var errorCode = (uint)e.ErrorCode;
switch (errorCode)
{
case RPC_E_SERVERCALL_RETRYLATER:
case RPC_E_CANTCALLOUT_INASYNCCALL:
return true;
default:
return false;
}
}
}
Excel的线程 与 SynchronizationContext的实现的更多相关文章
- 浅谈Excel开发:十 Excel 开发中与线程相关的若干问题
采用VSTO或者Shared Add-in等技术开发Excel插件,其实是在与Excel提供的API在打交道,Excel本身的组件大多数都是COM组件,也就是说通过Excel PIA来与COM进行交互 ...
- 利用SynchronizationContext.Current在线程间同步上下文
简而言之就是允许一个线程和另外一个线程进行通讯,SynchronizationContext在通讯中充当传输者的角色.另外这里有个地方需要清楚的,不是每个线程都附加SynchronizationCon ...
- 利用SynchronizationContext.Current在线程间同步上下文(转)
https://blog.csdn.net/iloli/article/details/16859605 简而言之就是允许一个线程和另外一个线程进行通讯,SynchronizationContext在 ...
- 浅谈Excel开发:六 Excel 异步自定义函数
上文介绍了Excel中的自定义函数(UDF ),它极大地扩展了Excel插件的功能,使得我们可以将业务逻辑以Excel函数的形式表示,并可以根据这些细粒度的自定义函数,构建各种复杂的分析报表. 普通的 ...
- 搞懂 SynchronizationContext(第一部分)【翻译】
SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...
- 搞懂 SynchronizationContext
SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...
- await之后的线程问题
之前看了园子里的一篇文章「async & await的前世今生」,收益颇多.而其中有句话被博主特意用红色标注,所以留意多看了几眼,「await 之后不会开启新的线程(await 从来不会开启新 ...
- 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationContext, CoreDispatcher, ThreadLocal, ThreadStaticAttribute
[源码下载] 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationCont ...
- C# Winform 跨线程更新UI控件常用方法汇总(多线程访问UI控件)
概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件的线程访问它”的异常.处理跨线程更新Winform UI控件常用的方法有4种:1. ...
随机推荐
- 05、python的基础-->字典的增、删、改、查
1.字典的增 dict = {'age':19,'name':'老王','hobby':'girl'} dict['sex'] = 'boy' #没有键值对,直接添加 dict[' #有键值对,覆盖值 ...
- selenium学习笔记(1)
selenium http://selenium-python.readthedocs.io/index.html https://www.seleniumhq.org/projects/ide/ 声 ...
- Struts2的Action访问
● 示例项目结构 ● demo1.jsp <%@ page language="java" import="java.util.*" pageEncod ...
- css中的居中问题
前两天写了一篇关于display:table的用法,里面涉及到居中的问题,这两天愈发觉得css中的居中是一个值得关注的问题,现总结如下. 一.垂直居中 (1)inline或者inline-*元素 1. ...
- join(long)方法和sleep(long)方法的比较
join(long)方法的源代码 public final synchronized void join(long millis) throws InterruptedException { long ...
- JNI Hello World
1.什么是JNI: JNI(Java Native Interface):java本地开发接口 JNI是一个协议,这个协议用来沟通java代码和 ...
- bash命令根据历史记录补全
用zsh比较方便的一个功能是在找之前用过的命令时可以先输入一部分命令作为过滤条件, 比如,想找 docker run 开头的历史命令,只需要键入 docker run 然后按 ↑ 进行选择. 但是在用 ...
- 聚合函数 -AVG/MAX/MIN/STDDEV/VARIANCE/SUM/COUNT/MEDIAN
------------------------------------------聚合函数--------------------------------------------- --1: AVG ...
- isPrototypeOf,hasOwnProperty
在看jquery源码的过程中,了解到isPrototypeOf属性.此属性只是Object.prototype的自有属性,即: Object.prototype.hasOwnProperty('isP ...
- HIVE了解及SQL基础命令
hive(数据仓库工具) Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据.它架构在Hadoop之上,总归为大数据,并使得查询和分析方便.并提供简单的sql查询功能,可以将sql语句转 ...