jazza1000
jazza1000

Reputation: 4247

Task Async confusion

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

Answers (3)

Claudio P
Claudio P

Reputation: 2203

Fix the code

You have to call the WCF service method in a different way:

var task = Task.Factory.StartNew(() => this._client.ReplicateData(credentialData));

Or use the magic

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

Yuval Itzchakov
Yuval Itzchakov

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:

Wcf settings

var replicatedData =  await _client.ReplicateDataAsync();

Upvotes: 1

SgtRock
SgtRock

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

Related Questions