在Excel中调用WCF方法切换“上下文”并让Word继续“工作”

我的问题很难解释,因为我不是100%确定我的自我,发生了什么事情。 我将尽我所能来解释这种情况。

只是一个警告,如果你希望有代码你必须看看,并试图find一个错误,恐怕我不能提供这样的事情,因为它是一个更普遍的问题,我面临的而不是在一个错误码。

所以…让我们开始

我有一个Excel AddIn,一个WPF应用程序和一个WCF服务器,所有我写的,我可以调整任何一方,如果这可能是neccassary。

在我的Excel AddIn中,我调用WCF服务器方法从WPF应用程序中检索数据。

在打开Excel工作簿后,我的AddIn将更新其值,因此调用WCF服务器。

这工作正常,当用户“正常”打开Excel工作簿,但失败时,这是“自动”的代码。

一种这样的情况是,所提到的Excel工作簿多次链接到一个MS Word文档中,例如一个字段函数

{ LINK Excel.Sheet.12 "C:\test.xlsx" "Sheet1!R1C1" } 

当用户打开MS Word文档,其中包含指向同一文件的多个链接时,MS Word将为每个链接打开Excel工作簿,在“评估”之后,它将closures工作簿。

所以,如果MS Word文档有10个链接到相同的Excel工作簿,它将打开/closures这个Excel工作簿10次。

这再次,是没有问题的。

现在,来抓住。

当用户有一个Excel实例运行时,在打开MS Word文档之前,它将无法打开第二个链接上的链接的Excel工作簿,并显示一条消息,说明该工作簿已经打开,如果第二次打开该工作簿,所有更改都会得到失去你想继续。

因此,出于某种原因,第一次打开Workbook时,MS Word未能将其closures。

通过大量的试验和错误,我将错误本地化为对我的WCF服务器的调用。

电话是:

 ReturnObject result = server.GetBatch(parameters, baseClass); 

当我调用这一行时,好像Excel不阻止MS Word继续工作,所以当MS Word已经试图closures并打开下一个链接时,我仍然在例程中从我的WCF服务器获取所有信息,由于我仍然有一个手头的Excel工作簿的参考,MS Word只是无法closures工作簿。

该方法在我的界面中定义为:

 [OperationContract()] ReturnObject GetBatch(List<Parameter> parameters, ClientInfo clientInfo); 

正如你所看到的,我不使用Task<ReturnObject> ,所以我期望它运行同步并阻止正在运行的线程。

我已经做了一些关于调用方法的testing,可以用这两种方法解决我的问题:

第一种方法:

 ReturnObject result = null; Thread th = new Thread(() => { result = server.GetBatch(parameters, baseClass); }); th.Start(); while (th.IsAlive) { } 

第二种方法:

 ReturnObject result = null; BackgroundWorker bw = new BackgroundWorker(); bw.DoWork += (sender, args) => { result = server.GetBatch(parameters, baseClass); }; bw.RunWorkerCompleted += (sender, args) => { }; bw.RunWorkerAsync(); while (bw.IsBusy) { } 

这两种方法基本上都是一样的,唯一的区别是第一个创build一个Thread和第二个BackgroundWorker

我想到了这两个目标是“卸载”到WCF服务器的调用,并用一个简单的while循环来阻塞调用线程。

你可以想象,我对这些“解决scheme”并不满意。

有没有办法让Excel在调用我的WCF服务器方法时“完全”阻塞?

实际上这里发生了什么,因为我没有真正了解到什么“魔法”正在发生,我只能猜测一些“Synchronization.Context”正在发生转换,但我真的没有线索?

重点是调用你的server.GetBatch 已经阻塞,但调用者只是一个并行任务活动的一部分。

与您的解决方法唯一的区别是while循环正在吃cpu资源,并间接阻止执行。

你可以真正考虑的是看WCF服务级别的pipe理并发性。

其中只有一个参考 :

当服务configuration为ConcurrencyMode.Single ,WCF将提供服务上下文的自动同步,并通过将包含服务实例的上下文与同步锁相关联来禁止并发调用。 每次进入服务的电话都必须先尝试获取locking。 如果锁是无主的,调用者将被允许进入。一旦操作返回,WCF将解锁该锁,从而允许另一个调用者。

对于更正确的WCF同步的扩展引用,这里是另一个链接 。

 [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)] public class BatchService : IBatchService { } 

在这里输入图像说明