memory leak in EWS - c#-4.0

We have a service application that uses Exchange Web Service.
We have the memory problem If I call one of the following lines of code in my service, that causes memory leak in my service application.
User application processes a lot of emails, so the memory usage will increase continuously and never be released again.
Code Examples.
var item = Item.Bind(mServiceWrapper.Service, ItemId.UniqueId);
var folder = Folder.Bind(mServiceWrapper.Service,item.ParentFolderId.UniqueId);
EmailMessage.Load(new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.MimeContent));
But if I start our program as an UI application, everything works fine without memory leak.
The problem occurs only when starting our program as a service.
Is the problem already known to you and do you have a solution?
I am using StreamingSubscript from EWS. Get the Emailas Exchange Server and store it in database.
private void OnNotificationEvent(object sender, NotificationEventArgs args)
{
var item = Item.Bind(mServiceWrapper.Service, mailItem.ItemId.UniqueId);
var folder = Folder.Bind(mServiceWrapper.Service, mailItem.ParentFolderId.UniqueId);
var propertySet = new PropertySet(BasePropertySet.FirstClassProperties);
item.Load(propertySet);
folder.Load(PropertiesProvider.FolderPropertySet);
object[] data = new object[]
{
item.Id.UniqueId,
folder.Id.UniqueId,
folder.ExtendedProperties.GetPropertyValue<long>(#"LexolutionContainerId"),
folder.ExtendedProperties.GetPropertyValue<int>(#"TrayId")
};
}
Another thread will load the emails and process the emails again. Like this
protected override void InternalWork(IJob job)
{
try
{
object[] data = (object[]) job.DataObject;
string itemUniqueId = (string) data[0];
ItemId itemId = new ItemId(itemUniqueId);
long targetContainerId = (long) data[2];
var propertySet = new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.MimeContent,
EmailMessageSchema.InternetMessageId);
var mail = Item.Bind(ExchangeWrapper.Service, itemId, propertySet);
}
}

You don't really give us enough code to be able to say for sure what your problem is -- but I can guess that you are not disposing of items correctly and/or the GC is not being called.
As a first step (and a general practice) I'd re-factor your code to use the using statement. Thus the code above would look like this:
var item = Item.Bind(mServiceWrapper.Service, ItemId.UniqueId);
var folder = Folder.Bind(mServiceWrapper.Service,item.ParentFolderId.UniqueId);
using (var props = new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.MimeContent))
{
EmailMessage.Load(props);
// additional code
}
There may be other places you can use using in your code, here is some documentation
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement
In addition you should look into forcing the GC to run in a service. This may be your problem too.

Related

How do I get information about why a background download is failing?

In WinRT, I am trying to spawn a background download and seem to be hitting my head against the wall. I have the following code:
var downloader = new BackgroundDownloader();
var operation = downloader.CreateDownload(new Uri(rendition.Url), resultingFile);
var downloadTask = operation.StartAsync().AsTask(new Progress<DownloadOperation>(ProgressHandler));
Stepping through the code one at a time, when I call CreateDownload() the resulting operation.Progres..Status is Idle, which is logical as I haven't started it yet.
However, if I take one step more so the StartAsync() runs, operation.Progress.Status now equals Error. My progress handler is never called.
Is there any way to get more detailed information about what the error is? I can't find anything to tell me what's wrong with the download.
First things first I can't see that you have assigned your
resultingFile
I use
StorageFile file = /* Instantiate */;
I'm creating a multiple tasks, because of the need to download many files.
Then I do it like this, referring to your code now
//List to hold my tasks
List<Task> dloadTasks = new List<Task>();
//SET callback
Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress);
//YOUR CODE!
var downloader = new BackgroundDownloader();
var operation = downloader.CreateDownload(new Uri(rendition.Url), resultingFile);
//Your code modified a bit
var yourResult = await operation.StartAsync().AsTask(progressCallback);
//This is where my way changes from your way
Task downloadCompletionTask = HandleDownloadAsync(operation , true);
//Add to list with tasks
dloadTasks.Add(downloadCompletionTask);
//Then i Await them
await Task.WhenAll(downloadCompletionTasks);

Why is my WinRT app closing when trying to debug my background task?

I am trying to experiment with downloading files on a regular basis with background tasks for windows store applications, and am having trouble.
I followed the sample at https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh977055.aspx, and even downloaded/ran it and everything worked perfectly (including being able to step into the timer background task).
So with that I created my own background task in a brand new Windows namespace
Win8BackgroundTest
{
public class TestBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
var deferral = taskInstance.GetDeferral();
var uri = new Uri("http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_480p_h264.mov");
var folder = ApplicationData.Current.LocalFolder;
var downloadFile = await folder.CreateFileAsync(uri.Segments.Last(), CreationCollisionOption.GenerateUniqueName);
var dataFile = await folder.CreateFileAsync("downloadData", CreationCollisionOption.GenerateUniqueName);
var downloader = new BackgroundDownloader();
var operation = downloader.CreateDownload(uri, downloadFile);
await FileIO.WriteTextAsync(dataFile, "Success at " + DateTime.Now);
deferral.Complete();
}
public static async void RegisterTask()
{
const string taskName = "TestBackgroundTask";
try
{
var status = await BackgroundExecutionManager.RequestAccessAsync();
if (status == BackgroundAccessStatus.Denied)
{
return;
}
}
catch
{
// already accepted
}
var tasks = BackgroundTaskRegistration.AllTasks
.Where(x => x.Value.Name == taskName)
.ToArray();
if (tasks.Any())
{
return;
}
var builder = new BackgroundTaskBuilder
{
Name = taskName,
TaskEntryPoint = "Win8BackgroundTest.TestBackgroundTask",
};
builder.SetTrigger(new TimeTrigger(60, false));
var registeredTask = builder.Register();
}
}
}
I set up the application's manifest with a Background Tasks declaration, checking the Timer properties checkbox, and set the EntryPoint to Win8BackgroundTest.TestBackgroundTask.
I then added the following at the end of my App.xaml.cs's OnLaunched() method:
TestBackgroundTask.RegisterTask();
Stepping through seems to have task registration work successfully with no exceptions. I then go back to visual studio, added a breakpoint to the first line in my task's Run() method, I then go to the debug locations toolbar, click the down arrow and select TestBackgroundTask. A few seconds later visual studio exits (as does my app).
Does anyone see what I am doing wrong that is causing background tasks to fail?
So after much frustration and a lot of trial and error the issue was a combination of both of the comments.
So first of all, it appears like you cannot have a background task in the same project as the rest of your windows store application. It must be in it's own windows runtime component project.
Finally, there are times where it just doesn't work and for whatever reason deleting the bin and obj folders fix it.

Trouble Attaching File Programmatically to Email in Windows Metro App C#/XAML using Share Charm

I'm simply trying to attach a file named Document.pdf in the DocumentsLibrary to an email using the Share Charm. My code below works perfectly on the Local Machine:
private async void OnDataRequestedFiles(DataTransferManager sender, DataRequestedEventArgs e)
{
List<IStorageItem> shares = new List<IStorageItem>();
StorageFile filetoShare = await Windows.Storage.KnownFolders.DocumentsLibrary.GetFileAsync("Document.pdf");
if (filetoShare != null)
{
shares.Add(filetoShare);
filetoShare = null;
}
if (shares != null)
{
DataPackage requestData = e.Request.Data;
requestData.Properties.Title = "Title";
requestData.Properties.Description = "Description"; // The description is optional.
requestData.SetStorageItems(shares);
shares = null;
}
else
{
e.Request.FailWithDisplayText("File not Found.");
}
}
But when I run the exact same code on a Windows Surface Tablet, I get the dreaded "There's nothing to share right now." on the right in the Charms flyout area.
Here's a little more background to help:
I'm not looking to use a File Picker...I know the exact file I'm looking for
I've enabled the Documents Library Capability in the manifest
I've added a File Type Association for pdf in the manifest
and yes, the file does exist and is in the Documents Library
an email account is properly setup in the Mail App on the surface
I can successfully send text emails from the Tablet...just not emails with attachments
Like I said, this works on my Win 8 Development Machine as expected...just not on the Surface. I'm wondering if the Surface has different file or folder permissions?
Thanks for the help...this is driving me CRAZY
I finally figured it out - the problem was that my Event Handler was async (so that I could use await to set the StorageFile variable).
I solved it by setting the StorageFile variable earlier in my code so that it was already available when the Event Handler was called.
I still have no idea why it worked on my development machine, but no on the WinRT surface...
The handler can be an async method. In this case, it is critical to use DataTransferManager. Please refer to the MSDN page specifically for this scenario. For your convenience, the code from the page is copied to here:
private void RegisterForShare()
{
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager,
DataRequestedEventArgs>(this.ShareStorageItemsHandler);
}
private async void ShareStorageItemsHandler(DataTransferManager sender,
DataRequestedEventArgs e)
{
DataRequest request = e.Request;
request.Data.Properties.Title = "Share StorageItems Example";
request.Data.Properties.Description = "Demonstrates how to share files.";
// Because we are making async calls in the DataRequested event handler,
// we need to get the deferral first.
DataRequestDeferral deferral = request.GetDeferral();
// Make sure we always call Complete on the deferral.
try
{
StorageFile logoFile =
await Package.Current.InstalledLocation.GetFileAsync("Assets\\Logo.png");
List<IStorageItem> storageItems = new List<IStorageItem>();
storageItems.Add(logoFile);
request.Data.SetStorageItems(storageItems);
}
finally
{
deferral.Complete();
}
}
It is critical to place the following statement before any async method is called:
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
You only have half a second to get the whole job done (getting the file, attaching...etc.). If the half-second deadline occurs you'll get this "driving crazy" message. Consider implementing some resumable logic and replace the message with "the attachment is being prepared please try again in a few seconds" (or else).
Your WinRT device might be just slower than your development machine. The latter just does the job before the deadline...

Transaction.Commit not flushing data to DB in NHibernate

I have a method/unit test case which has 2 transactions in it.
The id object which is persisted in the first transaction is being used in the second transaction. However the database/nhibernate is throwing an error that the persisted object is not present and the ID is invalid. However, looking at the database this is not the case and the entity is present.
Why is the query in the second transaction not able to recognize the entity persisted by the first one? Is the second one running before the first one has the chance to complete?
This issue is happening very irregularly but consistantly(about once or twice a week) in our smoke test builds. However I am not able to replicate this error on my local machine or on the server by running the tests manually.
How do I investigate/replicate/solve this problem?
Thanks,
Sandeep
[edit]
Here is the test case code:
public void UpdateContactMethodConfirmationStatus()
{
string workflowId = Guid.NewGuid().ToString();
try
{
Customer customer = null;
Preference preference = null;
//the first object is persisted here (the AddPreference call has the transaction.commit call
var preferenceRequest = new AddPreferenceRequest();
preferenceRequest.Preference = _adminMessageBuilder.CreateDoubleOptInPreference(3);
using (new TestTimer(TestContext, "CimAdminLoadTest", "AddPreference", workflowId))
preference = _service.AddPreference(preferenceRequest).Preference;
//the object persisted in above transaction is being used here(preference.id), AddCustomer call also has a transaction.commit
var request = _messageBuilder.GetAddCustomerRequest("I");
request.Customer.Preferences.Add(_messageBuilder.AddPreferenceContactMethod(preference.Id));
using (new TestTimer(TestContext, "CustomerLoadTest", "AddCustomer", workflowId))
customer = _service.AddCustomer(request).Customer;
var tenantContext = new TenantContext("CCC", "CCCTEST", "CCM");
var commPreference = customer.Preferences.Find(x => x.PreferenceId == preference.Id) as CustomerCommunicationPreference;
var contactMethod = commPreference.ContactMethods[0];
var key = CustomerPreferenceConfirmationKeyHelper.GenerateCustomerPreferenceConfirmationKey(contactMethod.Id, tenantContext);
var updateContactMethodConfirmationStatusRequest = new UpdateContactMethodConfirmationStatusRequest()
{
Channel = "PEG",
IsConfirmed = true,
ShortCode = "123",
CustomerPreferenceContactMethodKey = key
};
using (new TestTimer(TestContext, "CustomerLoadTest", "ResendNotifications", workflowId))
_service.UpdateContactMethodConfirmationStatus(updateContactMethodConfirmationStatusRequest);
}
catch (Exception ex)
{
Logger.WriteFailureMessage(ex.Message);
throw;
}
}

Are the CRM 2011 early bound APIs safe to use with the Task Parallel Library?

I am experiencing intermittent SaveChangesException when creating CRM entities using the early binding APIs (generated context) via a Threading.Task.
Using the code below I am able to recreate the exception - note that it is intermittent and I can have several runs without experiencing it.
As you can see there is no shared state in my code, I am creating the CRM Connection, service and context per operation.
The exception thrown is:
Microsoft.Xrm.Sdk.SaveChangesException: An error occured while processing this request. ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
Am I missing something here or are the early bound SDK classes unsafe to use in a multi-threaded environment?
class Program
{
static void Main(string[] args)
{
foreach (var index in Enumerable.Range(1, 400))
{
var capturedIndex = index;
Task.Factory.StartNew(() => CreateContact(capturedIndex));
}
Console.Read();
}
private static void CreateContact(int i)
{
var contact = new Contact {FirstName = "Test", LastName = string.Concat("Contact_", i)};
var context = new XrmServiceContext(new OrganizationService(new CrmConnection("Crm"))); // The generated context is taken from the SDK samples
context.AddObject(contact);
try
{
context.SaveChanges();
Console.WriteLine(string.Concat("Contact created - ", i));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
The exception occurs at a lower level within the WCF configuration. For those using late-bound entities, a workaround is to disable the ProxyTypesEnabled property on the CrmConnection. Another workaround is to set the ServiceConfigurationMode to PerInstance but unfortunately, this comes with a performance hit. Note: both of these can be set through the connection string as well.
var connection1 = new CrmConnection("Crm")
{
ProxyTypesEnabled = false
}; // late-bound only
var connection2 = new CrmConnection("Crm")
{
ServiceConfigurationInstanceMode = ServiceConfigurationInstanceMode.PerInstance
};

Resources