如何在.NET 4.0中正确使用async / await

时间:2016-11-14 11:08:44

标签: c# wcf asynchronous .net-4.0 async-await

由于某些原因我需要返回.net的版本,所以我是4.5,现在是im 4.0,并且我与我的异步方法有冲突: 我有wcf服务,我想执行异步方法并等待它们,所以在4.5我做了这个: WCF:

public async Task<DataTable> ProcessSomething(string Param1, int Param2)
        {
            return await Task.Run(() =>
            { 
            return new DataTable("aaa");
            });
        }

和4.5客户:

private static async Task<bool> ProcessSomethingAsync(string Param1, int Param2)
        {
            decimal payin = 0;
            Task<DataTable> result = Client.Instance.___Client.ProcessSomethingAsync(Param1, Param2);
            if (result == await Task.WhenAny(result, Task.Delay(1000)))
            {
                //code here..
            }
        }   

但当我恢复到4.0时,无论是服务还是客户端,我都必须使用nuget库:

  

https://www.nuget.org/packages/Microsoft.Bcl.Async/

现在在wcf 4.0中我有这个:

public async Task<DataTable> ProcessSomething(string Param1, int Param2)
        {
            return await Task.Factory.StartNew(() => 
            {
                return new DataTable("aaa");
            });
        }

在客户端我试试这个:

DataTable ProcessSomethingResult = await Client.Instance.____Client.ProcessSomethingAsync(Param1, Param2);

但错误弹出说:无法等待无效...... 如果我打电话:

DataTable ProcessSomethingResult = Client.Instance.____Client.ProcessSomething(Param1, Param2);

它返回datatable没有问题...但async返回void ..为什么?以及如何解决这个问题... tnx提前..

//在评论中你问我过程的定义,这里是:

public async Task<DataTable> ProcessTicket(string Barcode, int ClientID)
        {
            return await Task.Factory.StartNew(() => 
            {
                try
                {
                    DataTable dt = new DataTable("ProcessTicket");
                    using (SqlConnection con = new SqlConnection(TempClass._DatabaseConnectionString))
                    {
                        using (SqlCommand com = new SqlCommand("SELECT * FROM dbo.ProcessTicket(@Barcode, @ClientID)", con))
                        {
                            con.Open();
                            com.CommandType = CommandType.Text;
                            com.Parameters.AddWithValue("@Barcode", Barcode);
                            com.Parameters.AddWithValue("@ClientID", ClientID);
                            dt.Load(com.ExecuteReader());
                            if (dt == null)
                                throw new FaultException("DataTable from database is null.");
                            return dt;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logs.Instance.AppendLogs(ex.Message, MethodBase.GetCurrentMethod().Name);
                    throw new FaultException(ex.Message);
                }
            });
        }

1 个答案:

答案 0 :(得分:2)

在旧版本的WCF中,async函数与Begin / End语句绑定。使用基于任务的异步代理可能会导致问题,例如您正在运行。

重新生成您的客户端代理,以便您拥有Begin / End组合并使用TaskFactory.FromAsync将其转换为使用Microsoft.Bcl.Async时可以等待的任务。

//put this in a seperate file, client proxies are usually marked "partial" so you can 
// add functions on like this and not have them erased when you regenerate.
partial class YourClientProxy
{
    public Task<DataTable> ProcessSomethingAsync(string Param1, int Param2)
    {
        return Task<DataTable>.Factory.FromAsync(this.BeginProcessSomething, this.EndProcessSomething, Param1, Param2, null);
    }
}