Free Support Forum - aspose.com

Locking problem when using PrinterSettings

When calling new on PrinterSettingsContainer with a lock around the total method, the request will block all other requests to the service until the code is finished.
Moving the lock around the new PrinterSettingsContainer and adding a check to see if the printer is added to the collection again before calling the lock, will improve async request to the service.

protected override void OnBeginPrint(PrintEventArgs e)
{
base.OnBeginPrint(e);
switch (base.PrinterSettings.PrintRange)
{
case PrintRange.AllPages:
this.x2d6df7514a3346cc = 1;
this.xdef8a3063ecb3f83 = this.xd1424e1a0bb4a72b.PageCount;
break;

case PrintRange.SomePages:
this.x2d6df7514a3346cc = base.PrinterSettings.FromPage;
this.xdef8a3063ecb3f83 = base.PrinterSettings.ToPage;
break;

default:
throw new InvalidOperationException("Unsupported print range.");
}
this.xcb9cc4ea05847956();
}


private void xcb9cc4ea05847956()
{
PrinterSettingsContainer container;
string printerName = base.PrinterSettings.PrinterName;

/*lock (x4d25c27dfd0877ed)
{
if (x447698051be9d1ae.ContainsKey(printerName))
{
container = (PrinterSettingsContainer) x447698051be9d1ae[printerName];
}
else
{
container = new PrinterSettingsContainer(base.PrinterSettings); //Very slow
x447698051be9d1ae.Add(printerName, container);
}
}*/

if (x447698051be9d1ae.ContainsKey(printerName))
{
container = (PrinterSettingsContainer)x447698051be9d1ae[printerName];
}
else
{
lock (x4d25c27dfd0877ed)
{
if (x447698051be9d1ae.ContainsKey(printerName))
{
container = (PrinterSettingsContainer)x447698051be9d1ae[printerName];
}
else
{
container = new PrinterSettingsContainer(base.PrinterSettings); //Very slow
x447698051be9d1ae.Add(printerName, container);
}
}
}

this.xcb9cc4ea05847956(container);
}


Best regards,
Harald Nakstad
- DNB DSGI

Hi Lars,


Thanks for your inquiry. Perhaps you are using an older version of Aspose.Words. Please use the latest version of Aspose.Words for .NET. If you still face problem, please share your complete code here for testing. I will investigate the issue on my side and provide you more information.

Hi there,


We’ve downloaded the latest version of Aspose.Words and verified that the code is the same.
Thus the bug is still there. As Harald described earlier the implemented lock restricts execution flow of multiple concurrent threads trying to print in the same time interval. The current lock is thread safe but restricts the creation of PrintSettingsContainers to one after another, even if its allready cached and retrieved the printer settings in an earlier session. This is fairly visible when the retrieval of new printer settings from a device queue utilizes 30 seconds; then the complete print flow of multiple concurrent threads will have to wait until that completes. It manifests as burst printing.

The resolution that Harald presents resolves the situation by enabling cached requests to progress and thus is a better lock design in a multi-threaded environment. Though the thread-safetyness of ContainsKey during a concurrent Write must be evaluated.

We look forward to a fix as it is an issue in our production environment at the moment.

Best Regards,
Amund Letrud
- DNB DSGI

Hi Amund,


Please accept my apologies for late response. Aspose.Words is multithread safe as long as only one thread works on a Document at a time. It is a typical scenario to have one thread working on one document. Different threads can safely work on different documents at the same time.

Could you please share printing code (Visual Studio application) along with documents here for testing? I will investigate the issue on my side and provide you more information.

Hi there,


We have a printing service that manifests as a single process and spawns a new thread for each document to print. It is quite straight forward. The single process environment with multiple threads process indepentent print operations, i.e independent document and a print queue, locking will occure everytime for each thread when initializing and creating the required PrintSettingsContainer in Aspose.Words. If the print queue is new the locking implemented, as described earlier, will halt all other threads until device settings retrieval is completed. This turns problematic when the time taken to retrieve device / queue settings is long, like many seconds / minutes.

And yes the Aspose.Words is multithread safe but this part could be more efficient by enabling documents destined for print queues thats allready known to be forwarded. Now all requests have to wait the moment a new/unknown print queue is used.

Thank you for your assistanse and we look forward to a solution for our production situation :slight_smile:


Best Regards,
Amund Letrud
- DNB DSGI

Hi Amund,


Could you please share your code to reproduce this issue? I will investigate the issue on my side and provide you more information.

Hi!

I have tried to simulate our issue with different threads against the PrinterSettings object. The code could be executed in LinqPad (www.linqpad.com)

Best Regards,
Harald Nakstad
- DNB DSGI

Hi Harald,


Thanks for sharing the details. I have worked with your code and have not found any part of Aspose.Words which causes the locking issue. I have created a sample application based on your shared code/scenario and have not found the locking issue while testing it.

Could you please test the attached application at your side and share your finding with us? If the attached application does not fulfill your requirements, please modify the attached application according to your requirements and share it with us to reproduce this issue at our side.

Many Thanks,

Hi,

We have a global network (worldwide) with a potential of +4000 printers as target printer.

The issue we encounter is that Aspose.Words puts a blocking lock on the entire printer list during load of printer information by a call to win 32 api. This is blocking ALL other print jobs until that one printer settings is loaded. The windows api communicates with the remote printer to get settings and this may take up to 30-40 seconds in our network and is not acceptable by our users.

It is correct to put a lock on the load of printer information (as I believe the windows api call may not be thread safe) and the problem here is that even other printjobs that target printers where printer settings has been loaded is not allowed to perform print due to the blocking lock above.

Code decompiled with ILSpy:
protected override void OnBeginPrint(PrintEventArgs e)
{
base.OnBeginPrint(e);
switch (base.PrinterSettings.PrintRange)
{
case PrintRange.AllPages:
this.x2d6df7514a3346cc = 1;
this.xdef8a3063ecb3f83 = this.xd1424e1a0bb4a72b.PageCount;
break;

case PrintRange.SomePages:
this.x2d6df7514a3346cc = base.PrinterSettings.FromPage;
this.xdef8a3063ecb3f83 = base.PrinterSettings.ToPage;
break;

default:
throw new InvalidOperationException(“Unsupported print range.”);
}
this.xcb9cc4ea05847956();
}


private void xcb9cc4ea05847956()
{
PrinterSettingsContainer container;
string printerName = base.PrinterSettings.PrinterName;
// PUTS AN EXCLUSIVE LOCK MAKING INNER CODE SINGLE THREAD
lock (x4d25c27dfd0877ed)
{
if (x447698051be9d1ae.ContainsKey(printerName))
{
container = (PrinterSettingsContainer) x447698051be9d1ae[printerName];
}
else
{
// THIS LINE OF CODE MAY TAKE 30 to 40 SECONDS OR MORE
// TO COMMUNICATE WITH PRINTER TO GET SETTINGS

container = new PrinterSettingsContainer(base.PrinterSettings);
// UNCOMMENT NEXT LINE TO SIMULATE OUR ISSUE
// System.Threading.Thread.Sleep(40000);
x447698051be9d1ae.Add(printerName, container);
}
}
this.xcb9cc4ea05847956(container);
}

The initalization of a new PrinterSettingsContainer may take up to 30-40 seconds or more and happends within an exclusive lock and blocks ALL new print jobs - even jobs for printers where PrinterSettingsContainer has been loaded.!!!

Print goes through - no print jobs fail - but may be delayed for too long!!!
In our opinon due to “bad” code in Aspose.Words - to put the lock on the entire printerlist when loading printer settings for one printer - this blocks ALL other new print jobs.

The best solution would probably be to create a .NET4 version of Aspose.Words, use thread safe dictionary/lists and make the initialization of PrinterSettingsContainer single threaded (ie: within a lock statement).

If you want to “recreate” the issue - uncomment the line as shown above - recompile Aspose.Words and run your test application.

Best Regards,
Harald Nakstad
- DNB DSGI

Hi Harald,


Thanks for sharing the details. I have logged a new Task in our issue tracking system as WORDSNET-7804. Your request has been linked to this Task. Our development team will investigate the detail of PrinterSettingsContainer and we will update you via this forum thread about our findings on this issue.

We apologize for your inconvenience.

The issues you have found earlier (filed as WORDSNET-7804) have been fixed in this .NET update and this Java update.


This message was posted using Notification2Forum from Downloads module by aspose.notifier.