2015-10-13 75 views
1

在用戶界面中,我需要用戶從網絡上的所有可用實例中選擇一個SQL Server。我使用一個按鈕讓用戶點擊以顯示服務器。點擊按鈕後大約需要25秒,才能顯示列表。我想在加載頁面時準備好服務器列表。所以當用戶點擊按鈕時,列表已經準備就緒。但是,在頁面加載之前它會卡住。 RemoteSqlServers用於ItemSource。如何使用異步獲取網絡SQL服務器

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; 

    } 

我把它改成了下面,它在加載之前沒有卡住,但它仍然需要幾秒鐘。看起來async不工作,不知道爲什麼。

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; 
    } 
+0

將它的工作設置remoteSqlServers馬上空,然後在任務,填充它?對我來說,它似乎仍然在等待remoteSqlServers在繼續之前獲得一個值。 – Dylan

+0

如果我先將它設置爲null,那麼我應該在什麼時候從GetRemoteSqlServers()方法獲得真正的值? –

回答

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; 
     } 
    } 
} 
+3

他正在詢問異步/等待模式。 BackgroundWorker是一個退步。 –

+0

@Eric,你可以看看第二輪這個問題嗎? –

+0

我將它改爲: –

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); 
    } 
}