我们有一个WCF Web服务操作,用于生成PDF文件。我们正在使用第三方工具(Syncfusion),我们目前可能无法替换它。
问题在于,第三方工具似乎存在多线程问题,并且在某些情况下,当同时多次调用Web服务时无效。
我们可以通过使用lock
并确保只有一个线程执行临界区来解决问题:
Public Class GeneratorController
{
// object we use for lock
private static Object thisLock = new Object();
public void Generate(ref PdfDocument pdfDocument)
{
lock (thisLock)
{
// critical section
}
}
}
我的问题是:这是一个好主意吗?如果我们在Web服务中有这样的代码会导致任何问题吗?
注意
这不是关于Syncfusion的问题。这是关于在Web服务中使用lock
的问题。请不要将标签更改为syncfusion。
答案 0 :(得分:7)
我在这里看到的问题是资源匮乏。
锁定没有FIFO规则。因此,如果有连续负载,您可以得到这种情况:
A
声明锁定B
等待锁定C
等待锁定A
释放锁定。锁定是任意给予线程C
D
等待锁定。现在你有线程B
和D
都在等待。C
释放锁定。即使通过线程B
等待的时间最长,也可以随意将锁定给线程D
。所以它一直持续到WCF调用超时,并且你得到一个不可能重现的错误。
如果我必须实现这一点,我将有一个专门用于生成PDF文件的工作线程。该服务首次启动时将启动该线程,并等待从作业队列中取出作业。每个WCF查询都会在此队列上发出请求,并且在它知道已处理作业之前,它会有一些阻止的方式。
.NET 4.0提供了BlockingCollection
类来帮助解决这个问题。 (见this question)
这为您提供了没有完整解决方案的方法,因为它不是一个小问题。祝你好运!
答案 1 :(得分:4)
WCF支持同步调用服务对象,根据您的需要,您可能需要查看以下两个属性:
如果无法启动第三方组件的多个实例,并且组件不允许并发访问(最坏情况),则可以指定InstanceContextMode = Single,ConcurrencyMode = Single;在这种情况下,WCF将仅实例化WCF对象的单个副本(我假设它是第三方组件的包装),并且一次只处理一个请求。请求将排队并以FIFO方式处理。您不必在wcf服务中使用锁,因为WCF运行时确保您具有对wcf对象的同步访问权。
答案 2 :(得分:0)
Essential PDF是一个线程安全的组件 ,因此可以在多线程状态下创建PDF文档。你可以请创建一个Direct-trac事件以获得解决方案。