2011-03-26 35 views
1

我在寫一個必須訪問MySQL數據庫的程序。爲此,我編寫了一個PHP WebService以獲取表中的所有值。我遇到的問題是我正在用C#編寫一個函數來獲取這些值。我希望函數等待,直到調用DownloadStringCompleted事件的事件處理程序,然後返回值。我這樣做:System.Net.WebClient問題

WebClient client = new WebClient(); 
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(DownloadCompletedHandler); 
client.DownloadStringAsync(new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php")); 
while (DownloadCompleted == false) { } 
return DownloadResult; 

但是,這使得程序掛起。

我需要的東西,將暫停程序的一部分,直到DownloadConpleted = true。

我正在運行Visual Studio Ultimate 2010,我正在製作一個Silverlight應用程序,任何幫助將不勝感激。

回答

3

你可以使用一個ManualResetEvent - 信號從下載完成處理完成事件,並使得它的主線程等待:

ManualResetEvent completionEvent = new ManualResetEvent(false); 
WebClient webClient = new WebClient(); 
webClient.DownloadStringCompleted +=delegate(object sender, DownloadStringCompletedEventArgs e) 
{ 
    completionEvent.Set(); 
}; 

webClient.DownloadStringAsync(new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php")); 
completionEvent.WaitOne(); 

這回答了你的問題,但它仍然會使UI線程等待 - 你真的必須擁抱Silverlight的異步,所以你需要找到一個解決方案,在DownloadStringCompleted事件處理程序中更新你的模型 - 這樣你就不必使用柺杖,你的應用程序的性能會更好。

+0

與調用方法的阻塞版本不同:webClient.DownloadString(new Uri(「http://google.com」)); ??? – 2011-03-26 23:48:04

+2

@Mitch - 是的但在Silverlight afaik中不支持 - 這是啓用同步請求的柺杖,但正如評論中提到的,OP應該採用異步方法,而不是嘗試查找解決方法。 – BrokenGlass 2011-03-26 23:49:33

+0

啊,SilverLight!錯過了那一點。 – 2011-03-26 23:50:28

2

你可以使用一個ManualResetEvent

public string Download() 
{ 
    var manualEvent = new ManualResetEvent(false); 
    WebClient client = new WebClient(); 
    var result = string.Empty; 
    client.DownloadStringCompleted += (sender, e) => 
    { 
     if (e.Error != null) 
     { 
      result = e.Result; 
     } 
     manualEvent.Set(); 
    }; 
    client.DownloadStringAsync(new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php")); 
    // block while the download is completed and the event is signaled or 
    // timeout after 30 seconds 
    if (!manualEvent.WaitOne(TimeSpan.FromSeconds(30))) 
    { 
     // timeout 
    } 
    return result; 
} 

注意,阻止主線程是一種不好的做法,因爲這將凍結UI。更好的方法是簡單地處理下載完成的事件處理程序中的結果。並且由於此處理程序在不同於UI線程的線程上執行,因此不要忘記將任何將UI更新到主線程的調用。

推薦例如:

public void string Download() 
{ 
    var manualEvent = new ManualResetEvent(false); 
    WebClient client = new WebClient(); 
    client.DownloadStringCompleted += (sender, e) => 
    { 
     if (e.Error != null) 
     { 
      Dispatcher.BeginInvoke(() => 
      { 
       ResultLabel.Text = e.Result; 
      }); 
     } 
     else 
     { 
      Dispatcher.BeginInvoke(() => 
      { 
       ResultLabel.Text = e.Error.ToString(); 
      }); 
     } 
    }; 
    var url = new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php"); 
    client.DownloadStringAsync(url); 
} 

這樣,你不再阻塞主線程和UI保持液體狀態。一旦異步操作完成,您將通過使用Dispatcher.BeginInvoke方法將調用編組到UI線程來更新UI。

相關問題