任务全部结束时,连接正在关闭 [英] Task when all, connection is closing

查看:73
本文介绍了任务全部结束时,连接正在关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Task.WhenAll执行多个SqlDataReader.但是当任务等待时我得到

I'm trying to execute multiple SqlDataReaders using Task.WhenAll. But when the tasks are awaited I get

"System.InvalidOperationException:无效的操作.连接 已关闭".

"System.InvalidOperationException: Invalid operation. The connection is closed".

任务的创建:

        List<Task<SqlDataReader>> _listTasksDataReader = new List<Task<SqlDataReader>>();
        _listTasksDataReader.Add(GetSqlDataReader1(10));
        _listTasksDataReader.Add(GetSqlDataReader2(10));
        SqlDataReader[] _dataReaders = await Task.WhenAll(_listTasksDataReader);

我的"SqlDataReader"方法:

My "SqlDataReader" methods:

    public Task<SqlDataReader> GetSqlDataReader1(int recordCount)
    {
        using (var sqlCon = new SqlConnection(ConnectionString))
        {
            sqlCon.Open();
            using (var command = new SqlCommand("sp_GetData", sqlCon))
            {
                command.Parameters.Clear();
                command.Parameters.Add(new SqlParameter("@recordCount", recordCount));
                command.CommandType = System.Data.CommandType.StoredProcedure;
                return command.ExecuteReaderAsync();
            }
        }
    }

在执行Task.WhenAll时是否应该打开数据库连接,或者我丢失了什么?

Shouldn't the database connections be opened when the Task.WhenAll is executed or am I missing something?

推荐答案

更新:我将把它留在这里,但我只记得您不允许将yieldawait ...至少还没有.

UPDATE: I'm going to leave this here, but I've just remembered that you're not allowed to combine yield and await... at least, not yet.

请记住,即使使用return关键字调用command.ExecuteReaderAsync()也不会停止执行该方法.这就是_Async()方法的重点.因此,在该函数调用之后,代码立即退出using块.这样的效果是在您有机会使用连接对象从DataReader读取数据之前就将其放置.

Remember that calling command.ExecuteReaderAsync(), even with the return keyword, doesn't stop execution of the method. That's the whole point of _Async() methods. So immediately after that function call, the code exits the using block. This has the effect of disposing your connection object before you ever have a chance to use it to read from your DataReader.

尝试返回一个Task<IEnumerable<IDataRecord>>:

public async Task<IEnumerable<IDataRecord>> GetSqlDataReader1(int recordCount)
{
    using (var sqlCon = new SqlConnection(ConnectionString))
    using (var command = new SqlCommand("sp_GetData", sqlCon))
    {
        command.Parameters.Add("@recordCount", SqlDbType.Int).Value = recordCount;
        command.CommandType = System.Data.CommandType.StoredProcedure;

        sqlCon.Open();               
        var rdr = await command.ExecuteReaderAsync();
        while (rdr.Read())
        {
             yield return rdr;
        }
    }
}

请注意,此模式有一个陷阱".每个yield return使用相同的对象,因此,如果您不小心,可能会发生一些奇怪的事情.我建议进一步更改此包含代码,该代码将rdr对象中每个记录的数据放入其自己的(强类型)对象实例中:

Note that there is a "gotcha" with this pattern. Each yield return uses the same object, and therefore some weird things can happen if you aren't careful. I recommend further changing this include code that puts the data from each record in the rdr object into it's own (strongly-typed) object instance:

public async Task<IEnumerable<SomeObject>> GetSqlDataReader1(int recordCount)
{
    using (var sqlCon = new SqlConnection(ConnectionString))
    using (var command = new SqlCommand("sp_GetData", sqlCon))
    {
        command.Parameters.Add(new SqlParameter("@recordCount", recordCount));
        command.CommandType = System.Data.CommandType.StoredProcedure;

        sqlCon.Open();                
        var rdr = await command.ExecuteReaderAsync();
        while (rdr.Read())
        {
             yield return new SomeObject() {Field1 = rdr[1], Field2 = rdr[2], etc};
        }
    }
}

这篇关于任务全部结束时,连接正在关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆