Reputation: 4247
I have been asked to convert a WCF service call from synchronous to async, but the call seems to still be running synchronously. What am I doing wrong?
This is my service contract
[ServiceContract]
public interface ICredentialReplication
{
/// <summary>
/// Updates the store database with credential data
/// </summary>
/// <param name="credentials">the credential data to update</param>
[OperationContract]
Task ReplicateDataAsync(CredentialDataList credentials);
This is my implementation
/// <summary>
/// Copy the credential data to the stores
/// </summary>
/// <param name="credentials">The credential data to copy</param>
public async Task ReplicateDataAsync(CredentialDataList credentials)
{
var task = Task.Factory.StartNew(() => UpdateData(credentials));
await task;
}
I have generated the proxy classes with the "generate asynchronous operations" flag set in the client, and I call the service with the following code (service call is right at the end)
foreach (var store in storedic)
{
// call the replication service for that store
CredentialDataList credentialData = new CredentialDataList();
List<CredentialData> credentialList = new List<CredentialData>();
foreach (var payroll in store)
{
CredentialData cred = this.ExtractCredentialData(data, pinData, payroll);
credentialList.Add(cred);
}
credentialData.CredentialList = credentialList.ToArray();
credentialData.PermissionList = permDataList;
credentialData.PermissionTypeList = permTypeDataList;
// then call the service
this._client.ReplicateData(credentialData);
}
I had thought that stepping through this loop in the debugger should come back straight away, but instead it waits for the service call to complete before it returns. Am I missing something?
Upvotes: 2
Views: 200
Reputation: 2203
You have to call the WCF service method in a different way:
var task = Task.Factory.StartNew(() => this._client.ReplicateData(credentialData));
Or another possibility would be to keep the same code of the service and just configure the client to call the servie asynchronously. This configuration can be done by changing the properties of the service refference in the visual studio. After the configuration you can simply use the method called <MethodName>Async()
. No changes needed on the service side.
[Edit]
How your code should look like after:
Service Contract:
[ServiceContract]
public interface ICredentialReplication
{
/// <summary>
/// Updates the store database with credential data
/// </summary>
/// <param name="credentials">the credential data to update</param>
[OperationContract]
void ReplicateData(CredentialDataList credentials);
}
Implementation:
/// <summary>
/// Copy the credential data to the stores
/// </summary>
/// <param name="credentials">The credential data to copy</param>
public void ReplicateData(CredentialDataList credentials)
{
UpdateData(credentials);
}
Consume of the service:
this._client.ReplicateDataAsync(credentialData);
Hope this helps
Upvotes: 0
Reputation: 149538
It seems as if you're using the synchronous version of your client API instead of the asynchronous version:
this._client.ReplicateData(credentialData);
Instead of using the async over sync anti-pattern, i'd suggest that instead use the synchronous version of the API.
Use WCF to generate a task based operation which you can await:
var replicatedData = await _client.ReplicateDataAsync();
Upvotes: 1
Reputation: 191
You are calling your old synchronous method in your implementation.
this._client.ReplicateData(credentialData);
You would call the async version like so:
await this._client.ReplicateDataAsync(credentialData);
Your method signature would also need the async modifier if it doesn't already.
Upvotes: 1