Reputation: 2442
I have the following code for a class. This is the initialize of a class.
Third Party DLL
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
protected void initialize()
{
if (_initialized)
{
return;
}
if (_hdc == IntPtr.Zero)
{
_hdc = GDI32.CreateCompatibleDC(IntPtr.Zero);
if (_hdc == IntPtr.Zero)
{
throw new GDIException("Failed to create compatible device context.");
}
}
if (_hFontOld == IntPtr.Zero)
{
_hFont = FontSettings.GenerateHFont(_fontSetting, _hdc, _dpi, _forceFixedPitch);
_hFontOld = GDI32.SelectObject(_hdc, _hFont);
}
_initialized = true;
updateHeightAndWidth();
}
Sorry I didn't post the Dispose. Here it is!. This is a 3rd party DLL causing this error every 3- 4 hrs on production. Our company uses this 3rd party software. This error didn't happen before the upgrade. Third Party DLL.
protected virtual void Dispose(bool isDisposing)
{
if (_isDisposed)
{
return;
}
releaseOldBitmap();
if (_hFont != IntPtr.Zero)
{
if (_hFontOld != IntPtr.Zero && _hdc != IntPtr.Zero)
{
GDI32.SelectObject(_hdc, _hFontOld);
}
if (GDI32.DeleteObject(_hFont))
{
_hFont = IntPtr.Zero;
}
}
if (_hdc != IntPtr.Zero && GDI32.DeleteDC(_hdc))
{
_hdc = IntPtr.Zero;
}
_isDisposed = true;
}
~TextPageRenderer()
{
Dispose(isDisposing: false);
}
public void Dispose()
{
Dispose(isDisposing: true);
GC.SuppressFinalize(this);
}
This code in production works very well. But every 4hrs or so after some load on the server, GDI32.CreateCompatibleDC(IntPtr.Zero) returns IntPtr.Zero and the exception throw new GDIException("Failed to create compatible device context.") is thrown
Our code: This is how I use the 3rd party DLL in our code
#region ExternalText
public static DocumentsList ExternalText(Application obApp, int? _RequestCount, int[] _ItemTypeIDs, KeywordIdPairs _Keywords, Constraints _Constraints)
{
var Results = new DocumentsList();
TextSearchResults textSearchResults;
var _SearchString = "";
DateTime startDate;
DateTime endDate;
long startDocumentId;
long endDocumentId;
var textSearchOptions = new TextSearchOptions();
var docQuery = obApp.Core.CreateDocumentQuery();
var textProvider = obApp.Core.Retrieval.Text;
try
{
var keywords = obApp.Core.KeywordTypes;
startDocumentId = 1;
endDocumentId = 10;
docQuery.AddDocumentRange(startDocumentId, endDocumentId);
var documentList = docQuery.Execute(Convert.ToInt32(_RequestCount));
_SearchString = "0916";
if (!String.IsNullOrEmpty(_SearchString))
{
foreach (var document in documentList)
{
var keyValueList = new KeyValueList<string, string>();
if (document != null && document.DefaultRenditionOfLatestRevision != null && document.DefaultRenditionOfLatestRevision.FileType != null && document.DefaultRenditionOfLatestRevision.FileType.Extension == "ctx")
{
textSearchResults = textProvider.TextSearch(document.DefaultRenditionOfLatestRevision, _SearchString, textSearchOptions);
foreach (var textSearchResult in textSearchResults)
{
var t = typeof(TextSearchItem);
PropertyInfo[] properties = t.GetProperties();
keyValueList.Add(ExternalTextRequest.DocID, document.ID.ToString());
keyValueList.Add(ExternalTextRequest.DocName, document.Name);
keyValueList.Add(ExternalTextRequest.DocumentType, document.DocumentType.Name);
foreach (PropertyInfo pi in t.GetProperties())
{
if (pi.Name == "SizeX")
{
keyValueList.Add(ExternalTextRequest.Width, pi.GetValue(textSearchResult, null).ToString());
}
else if (pi.Name == "SizeY")
{
keyValueList.Add(ExternalTextRequest.Height, pi.GetValue(textSearchResult, null).ToString());
}
}
Results.Add(keyValueList);
}
}
else
{
}
}
}
return Results;
}
catch (UnityAPIException e)
{
throw e;
}
catch (Exception ex)
{
throw ex;
}
return Results;
}
enter code here
The aboce snippet is my code using TextDataProvider I create an instance of TextDatProvider and call the textsearch from the API. The same code gets called more than 1000 times in 2 hrs. It is called for different search string, document ID's. TextSearch is heavily used.
How do I troubleshoot this problem. Could this be a memory leak? I cannot make it happen on test or development. This is a .NET application that references a 3rd party component. This code is part of their component. Nothing changed except this 3rd party component which got upgraded.
Upvotes: 0
Views: 444
Reputation:
Also, one more question..would a App pool reset clear up GDI objects?
You mentioned that your app is running in IIS. When an IIS AppPool is recycled or times out (usually after 20 minutes), IIS unloads the AppDomain for the IIS app. The AppDomain is given a chance to handle this event for clean-up purposes.
For ASP.NET apps this will be the Application_End
method. Be sure to release any GDI objects (including DCs and fonts) here.
Upvotes: 1