首页 > 解决方案 > 使用异步查询多个 MySQL 实例 - 分片环境

问题描述

我正在构建一个使用 MVC 对分片 MySQL 环境运行查询的工具。当前工具的工作方式是让用户输入查询,选择他们的数据库,然后选择实例。因此,我可以从中构建连接字符串并将它们添加到列表中并将它们传递给我的查询数据库类中的方法。这很好用,但会很慢,因为它是同步的。

如何将我的同步 foreach 循环转换为异步方法?

以下是我目前从服务器获取数据的方法:

public DataSet getResults(List<string> connstrings, string query)
{
    foreach (string con in connstrings)
    {
        DataSet masterDS = new DataSet();

        MySqlConnection conn = new MySqlConnection(con);
        try
        {
            conn.Open();
            MySqlCommand cmd = new MySqlCommand(query, conn);
            MySqlDataAdapter da = new MySqlDataAdapter(cmd);
            DataSet ds = new DataSet();
            da.Fill(ds);                    
            masterDS.Merge(ds);           

        }
        catch (MySqlException ex)
        {
            int errorcode = ex.Number;

        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.ToString());
        }
        finally
        {
            conn.Close();
        }           
    }

    Return MasterDS;
}

此外,我不会将结果存储在内存中,而是将它们写入服务器上的文件。

标签: c#mysqlasynchronous

解决方案


老实说,不知道是否DataSet会喜欢这个,如果这是线程安全的。但这是您可以对 CPU 密集型任务执行的一件事:

public DataSet getResults(List<string> connstrings, string query)
{
    var tasks = new List<Task>();
    DataSet masterDS = new DataSet();

    foreach (string con in connstrings)
    {

        tasks.Add(Task.Run(() = 
        {
            MySqlConnection conn = new MySqlConnection(con);
            try
            {
                conn.Open();
                MySqlCommand cmd = new MySqlCommand(query, conn);
                MySqlDataAdapter da = new MySqlDataAdapter(cmd);
                // NOTE changes here
                da.Fill(masterDS);                    

            }
            catch (MySqlException ex)
            {
                int errorcode = ex.Number;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
            finally
            {
                conn.Close();
            }   
        });     
    }

    Task.WaitAll(tasks.ToArray());

    Return MasterDS;
}

潜在地,您可能想要返回到Merge. 只有在所有任务完成后才这样做。如果您想变得非常复杂,可以调用Task.ContinueWith,将每个 DS 添加到并发队列中,然后再使用另一个Task.Run...,它从该队列中获取并在单个线程上合并 DS,同时仍在填充 DS。所以,等到完成的时候Task.WaitAll,你就完成了


推荐阅读