Reputation: 930
We are having trouble with a background call from our WPF application. Seemingly, on older computers (we have seen it most often on Windows 7 machines with 2GB of RAM or so) our web service call blocks the UI until it completes. For one call in particular, that is a huge problem because it can take five minutes to complete. Newer computers seem to handle it fine.
We don't care about the amount of time the call takes; we only care about it not blocking the UI. I do not see anything we are doing wrong off-hand.
Are we doing something wrong, or is it something with Windows 7 on 2GB of RAM? Is theere any way to work around it on such a machine?
Do we have to go to the level of writing a custom TaskScheduler
to make sure the UI thread does not get used? I sure hope not.
Any input at all is greatly appreciated. Thanks in advance. See code samples below.
DownloadBusinessEntityAsync
is the method our application calls:
#region DownloadBusinessEntity
public async Task<BusinessEntity> DownloadBusinessEntityAsync(string businessEnityId)
{
BusinessEntity ret = new BusinessEntity();
var client = new DownloadContext();
try
{
Func<AsyncCallback, object, IAsyncResult> begin = (callback, state) => client.BeginDownloadBusinessEntity(businessEnityId, callback, state);
Func<IAsyncResult, BusinessEntity> end = client.EndDownloadBusinessEntity;
// ***THIS TAKES FIVE MINUTES TO FINISH***
ret = await Task<BusinessEntity>.Factory.FromAsync(begin, end, null);
if (client.State != CommunicationState.Faulted)
client.Close();
else
client.Abort();
}
catch (Exception ex)
{
client.Abort();
}
return ret;
}
#endregion
DownloadContext
is the WCF client:
public partial class DownloadContext : ClientBase<IDownloadService>, IDownloadService, IDownloadContext, IDisposable
{
public BusinessEntity DownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes)
{
return base.Channel.DownloadBusinessEntity(agencyId, activeHashCodes);
}
public IAsyncResult BeginDownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes, AsyncCallback callback, object asyncState)
{
return base.Channel.BeginDownloadBusinessEntity(agencyId, activeHashCodes, callback, asyncState);
}
public BusinessEntity EndDownloadBusinessEntity(IAsyncResult result)
{
return base.Channel.EndDownloadBusinessEntity(result);
}
}
IDownloadService
is the contract the WCF client implements.
[ServiceContract(Namespace = "http://namespace.com/services/v1")]
public partial interface IDownloadService
{
[OperationContract(ProtectionLevel=ProtectionLevel.Sign, Action="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntity", ReplyAction="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntityResponse")]
BusinessEntity DownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes);
[OperationContract(AsyncPattern=true, ProtectionLevel=ProtectionLevel.Sign, Action="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntity", ReplyAction="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntityResponse")]
IAsyncResult BeginDownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes, AsyncCallback callback, object asyncState);
BusinessEntity EndDownloadBusinessEntity(IAsyncResult result);
}
Upvotes: 1
Views: 979
Reputation: 456717
There is a known problem with Microsoft's implementation of client-side HTTP connections (HttpWebRequest
and friends): they do some work synchronously, including DNS resolution and (I believe) proxy detection. This work is always done synchronously even for an asynchronous request, and it may take some time depending on your network configuration.
I'm not sure if the WCF clients share this bug, but it's likely. The best workaround is to wrap it in a Task.Run
as per usr's answer.
Upvotes: 2
Reputation: 171218
If you simply don't want to block the UI then move that work to a background thread. All that async WCF stuff is not needed to achieve your goal. Something like:
await Task.Run(() => DownloadBusinessEntityAsync(...));
And you can make DownloadBusinessEntityAsync
sync if you like.
Upvotes: 1