任务异步混乱

Task Async confusion

有人要求我将 WCF 服务调用从同步转换为异步,但调用似乎仍然是 运行 同步。我做错了什么?

这是我的服务合同

[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);

这是我的实现

/// <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;  
    }

我已经在客户端生成了带有"generate asynchronous operations"标志的代理类,我用下面的代码调用服务(服务调用就在最后)

 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);     
            }               

我原以为在调试器中单步执行这个循环应该会立即返回,但它会在它之前等待服务调用完成 returns。我错过了什么吗?

修正代码

您必须以不同的方式调用 WCF 服务方法:

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

或者使用魔法

或者另一种可能性是保留相同的服务代码,只是将客户端配置为异步调用服务。此配置可以通过更改 visual studio 中服务引用的属性来完成。配置完成后,您可以简单地使用名为 <MethodName>Async() 的方法。服务端无需更改。

[编辑]

你的代码在之后应该是什么样子:

服务合同:

[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);
}

实施:

/// <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); 
}

服务消费:

this._client.ReplicateDataAsync(credentialData);

希望对您有所帮助

您在实现中调用了旧的同步方法。

this._client.ReplicateData(credentialData);

您可以这样调用异步版本:

await this._client.ReplicateDataAsync(credentialData);

如果您的方法签名还不需要 async 修饰符,那么它也需要它。

您似乎使用的是 同步 版本的客户端 API 而不是 异步 版本:

this._client.ReplicateData(credentialData); 

我建议不要使用 async over sync anti-pattern,而是使用 API.

synchronous 版本

使用 WCF 来 generate a task based operation 您可以等待:

var replicatedData =  await _client.ReplicateDataAsync();