C# 如何在.NET4.0中正确使用async/await

C# 如何在.NET4.0中正确使用async/await,c#,wcf,asynchronous,.net-4.0,async-await,C#,Wcf,Asynchronous,.net 4.0,Async Await,出于某些原因,我需要回到.net版本,所以我当时是4.5,现在是im 4.0,我与我的异步方法有冲突: 我有wcf服务,我想执行异步方法并等待它们,所以在4.5中我做了如下操作: 周转基金: 但错误突然冒出来说:不能等待空虚。。。 如果我打电话: DataTable ProcessSomethingResult = Client.Instance.____Client.ProcessSomething(Param1, Param2); 它返回datatable没有问题。。。但是async正在返

出于某些原因,我需要回到.net版本,所以我当时是4.5,现在是im 4.0,我与我的异步方法有冲突: 我有wcf服务,我想执行异步方法并等待它们,所以在4.5中我做了如下操作: 周转基金:

但错误突然冒出来说:不能等待空虚。。。 如果我打电话:

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);
                }
            });
        }
公共异步任务进程票证(字符串条形码,int-ClientID)
{
return wait Task.Factory.StartNew(()=>
{
尝试
{
DataTable dt=新的DataTable(“ProcessTicket”);
使用(SqlConnection con=newsqlconnection(TempClass.\u DatabaseConnectionString))
{
使用(SqlCommand com=newsqlcommand(“SELECT*FROM dbo.ProcessTicket(@Barcode,@ClientID)”,con))
{
con.Open();
com.CommandType=CommandType.Text;
com.Parameters.AddWithValue(“@Barcode”,条形码);
com.Parameters.AddWithValue(“@ClientID”,ClientID);
Load(com.ExecuteReader());
如果(dt==null)
抛出新的FaultException(“数据库中的DataTable为null”);
返回dt;
}
}
}
捕获(例外情况除外)
{
Logs.Instance.AppendLogs(例如Message,MethodBase.GetCurrentMethod().Name);
抛出新的FaultException(例如消息);
}
});
}

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

重新生成您的客户端代理,这样您就有了开始/结束组合,并使用它将其转换为一个任务,使用
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);
    }
}
//将其放在一个单独的文件中,客户端代理通常被标记为“部分”,因此您可以
//像这样添加函数,并且在重新生成时不会删除它们。
部分类YourClientProxy
{
公共任务ProcessSomethingAsync(字符串Param1,int Param2)
{
返回Task.Factory.fromsync(this.BeginProcessSomething,this.EndProcessSomething,Param1,Param2,null);
}
}

似乎我们在Client.Instance中看不到最相关的代码。\uuuuuuuuuu Client,这是从生成的客户端接口生成的吗?这是与wcf服务交互的客户端对象的单例模式。Client.Instance.ClientObjectName.SomeMethod();不过,这就是问题所在。你为什么这么认为?你能告诉我们Client.Instance.\uuuuu Client.ProcessSomethingAsync()的定义吗?谢谢你,长官,任务完成:)@Srgjan LDTeam你应该点击我答案旁边的复选标记来标记答案完成。
DataTable ProcessSomethingResult = await Client.Instance.____Client.ProcessSomethingAsync(Param1, Param2);
DataTable ProcessSomethingResult = Client.Instance.____Client.ProcessSomething(Param1, Param2);
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);
                }
            });
        }
//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);
    }
}