如何使用async获取网络SQL Server

时间:2015-10-13 18:54:41

标签: c# sql-server wpf

在用户界面中,我需要用户通过网络从所有可用实例中选择SQL服务器。我使用一个按钮让用户单击以显示服务器。单击按钮大约需要25秒才能显示列表。我正在考虑在加载页面时准备好服务器列表。因此,当用户单击按钮时,列表已准备就绪。但是,它在页面加载之前就会卡住。 remoteSqlServers用于ItemSource。

 internal static ObservableCollection<string> remoteSqlServers = GetRemoteSqlServers().Result;   

    public static async Task<ObservableCollection<string>> GetRemoteSqlServers()
    {

        var SqlServers = await Task<ObservableCollection<string>>.Run(() =>
        {
            return new SqlEnumerationHelper().SqlEnumerateRemote();

        }).ConfigureAwait(false);

        return SqlServers;

    }

我将其更改为低于它在加载之前不会卡住,但仍需要几秒钟。似乎异步操作起作用并且不知道为什么。

 public static ObservableCollection<string> remoteSqlServers = new ObservableCollection<string>();

 public GetSqlViewModel()
{
  ...
    remoteSqlServers = GetRemoteSqlServers().Result;
  ...
 }

   public static async Task<ObservableCollection<string>> GetRemoteSqlServers()
    {

        var SqlServers = await Task<ObservableCollection<string>>.Run(() =>
        {
            return new SqlEnumerationHelper().SqlEnumerateRemote();

        }).ConfigureAwait(false);
        return SqlServers;

    }

这是SqlEnumerateRemote:

  public ObservableCollection<string> SqlEnumerateRemote()
    {
        ObservableCollection<string> sqlServerNames = new ObservableCollection<string>();
        LogHelper.log("SqlEnumerationHelper:SqlEnumerateRemote", "Starting");

        try
        {
            //Make an initial call to the sql browser service to wake it up
            using (DataTable sqlSources = SqlDataSourceEnumerator.Instance.GetDataSources())
            {
                //There are issues with SqlDataSourceEnumerator, that it doesn't always return all sql instances
            }

            SqlDataSourceEnumerator instance = SqlDataSourceEnumerator.Instance;
            System.Data.DataTable dt = instance.GetDataSources();
            DataRow[] rows = dt.Select(string.Empty, "ServerName asc");

            if (rows.Length > 0)
            {
                foreach (DataRow dr in rows)
                {
                    string serverName = dr["ServerName"].ToString();
                    string instanceName = dr["InstanceName"].ToString();
                    if (instanceName.Length > 0)
                        serverName += "\\" + instanceName;
                    sqlServerNames.Add(serverName);
                }
            }
            LogHelper.log("SqlEnumerationHelper:SqlEnumerateRemote", "Ending");
        }
        catch (Exception e)
        {
            LogHelper.log("SqlEnumerationHelper:SqlEnumerateRemote", "SqlDataSourceEnumerator.GetDataSources and assoc processing failed" + e.Message);
        }

        return sqlServerNames;
    }

2 个答案:

答案 0 :(得分:0)

编辑:对于这个问题,这个答案不是正确的,尽管我会为偶尔的路人留下它。

尝试一下BackgroundWorker,它们非常适合从繁琐的UI中解脱出来。

using System.Collections.ObjectModel;
using System.ComponentModel;

internal static ObservableCollection<string> remoteSqlServers;

public BackgroundWorker Sync = new BackgroundWorker();
public MyControl()
{
    InitializeComponent();

    remoteSqlServers = new ObservableCollection<string>();

    Sync.DoWork += Sync_DoWork;
    Sync.RunWorkerCompleted += Sync_RunWorkerCompleted;
    Sync.WorkerSupportsCancellation = true;
    Sync.RunWorkerAsync();

}

private void Sync_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    if ((worker.CancellationPending == true))
    {
        e.Cancel = true;
    }
    else
    {
        return SqlEnumerationHelper().SqlEnumerateRemote();
    }
}

private void Sync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if ((e.Cancelled == false))
    {
        if (e.Result != null)
        {
            remoteSqlServers = (SqlServers)e.Result;
        }
    }
}

答案 1 :(得分:0)

第二轮!

我不确定SqlEnumerateRemote()到底是什么,但这不应该挂起你的代码,因为它的作用很神奇。

当您尝试加载remoteSqlServers时,它正在等待您的操作在初始化之前完成。

初始化,然后像这样加载:

internal static ObservableCollection<string> remoteSqlServers = new ObservableCollection<string>();

public MyControl()
{
    InitializeComponent();
    GetRemoteSqlServers();
    //so on and so forth
}

public static async Task GetRemoteSqlServers()
{
    foreach (var item in (await Task.Run(() =>
    { return new SqlEnumerationHelper().SqlEnumerateRemote(); })))
    {
        remoteSqlServers.Add(item);
    }
}