We have a Windows Service that is using GenerateHTML method to load the document cache so users do not have to wait for the Viewer to render the documents.
I am trying to change this to be multithreaded and I am running into many issues. Have you ever used the GenerateHtml in a multithreaded scenario?
Using Parallel.Foreach I tried instantiating an object for each thread. If I do that I receive the following error for this code:
Parallel.ForEach()
{
////custom code
DocumentCache dc = new DocumentCache(null, storageLocation);
dc.GenerateHtml(documentPath, “our url”, false, false);
///custom code
}
ERROR DocumentPreviewCache - failed for file: 910600 Exception has been thrown by the target of an invocation. at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at (Object , Object[] )
at ..(Stream stream, Boolean forceApply)
at Groupdocs.Web.UI.DocumentCache…ctor(String licensePath, String rootStoragePath, String workingDirectoryPath)
at ControleEngine.DocumentPreviewCache.ProcessDocumentCache(FolderDetail file, Boolean rewrite) in DocumentPreviewCache.cs:line 210
If I run that same code with the Parallel option of 1 max thread it runs fine.
I changed the code to use a global DocumentCache object and it seemed to be working but after a few hours it became very slow and eventually the app crashed.
DocumentCache _dc = new DocumentCache();
Parallel.ForEach()
{
////custom code
_dc.GenerateHtml(documentPath, “our url”, false, false);
///custom code
}
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ObjectDisposedException
Stack:
at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean ByRef)
at Microsoft.Win32.Win32Native.SetEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle)
at System.Threading.EventWaitHandle.Set()
at System.Runtime.Remoting.Messaging.AsyncResult.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage)
at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessageSink)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
Any thoughts on using your API in this scenario? Thanks