2011-08-16 23 views
1

我有一個刷新按鈕來更新我的WP7應用程序中的新聞。當我雙擊或三擊刷新按鈕時,我得到一個錯誤C# - 併發I/O操作異常

"WebClient does not support concurrent I/O operations" . 

我認爲這是因爲它發送請求三倍,並使其崩潰。這是我的Click代碼。

private void NewsRefresh_Click(object sender, RoutedEventArgs e) 
    { 
     var vm = this.DataContext as MainPageViewModel; 
     if (vm != null) 
     { 
      vm.UpdateNews(); 
     } 
    } 

我該怎麼把它變成「如果它忙取消進程」。

+0

介紹私人布爾isPendingRefresh – sll

+0

任何線索或指南呢? – FrankCap

回答

1

的「易」的方式(儘管不是防彈):

private void NewsRefresh_Click(object sender, RoutedEventArgs e) 
{ 
    try 
    { 
     NewsRefresh.Enabled = false; 
     var vm = this.DataContext as MainPageViewModel; 
     if (vm != null) 
     { 
      vm.UpdateNews(); 
     } 
    } 
    finally 
    { 
     NewsRefresh.Enabled = true; 
    } 
} 

更困難的方案需要什麼完全是一個MainPageViewModel是,什麼UpdateNews更多詳細資料()一樣。基本上你需要在你存儲WebClient實例的地方存儲一個狀態值。在使用WebClient之前,您需要檢查您是否已經在使用它。如果多個線程可能在單個實例上運行,或者您有多個操作(UpdateNews除外),則會出現此問題。當涉及多個線程時,最簡單的方法是將WebClient的使用用Mutex包圍。

當然,其他選項是不重用WebClient實例,而是爲每個新請求創建一個新實例。

UPDATE

好,好,使用DownloadStringAsync肯定會讓情況變得有趣。上述代碼除非您移動重新啓用代碼,否則禁用UI將不起作用。使用我最後的建議最簡單,並創建WebClient的新實例。我並不是真正喜歡WebClient,而更喜歡使用WebRequest.Create

+0

我會檢查一下。順便說一句,UpdateNews()正在下載feed newsWebClient.DownloadStringAsync(new Uri(「http://feeds.bbci.co.uk/news/rss.xml」)); – FrankCap

2

WebClient不是很靈活,但如果你真的想使用它,你可以使用IsBusy屬性,然後取消正在進行的操作。然後,一旦它被取消,你可以重新啓動它。同步存在重要問題。包含檢查IsBusy和調用CancelAsync的操作不是原子操作。幸運的是DownloadStringCompleted被分派到UI線程,所以你不需要擔心同步。下面的代碼片段展示瞭如何實現它。爲了簡單起見,它是Windows窗體。

public partial class Form1 : Form 
{ 
    WebClient _WebClient; 
    bool _UpdateNews; 

    public Form1() 
    { 
     InitializeComponent(); 
     _WebClient = new WebClient(); 
     _WebClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(_WebClient_DownloadStringCompleted); 
     _UpdateNews = false; 
    } 

    void _WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 
    { 
     if (_UpdateNews) 
     { 
      _UpdateNews = false; 
      UpdateNews(); 
     } 
     else if (e.Error != null) 
     { 
      // Report error 
     } 
     else 
     { 
      MessageBox.Show(e.Result); 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     if (_WebClient.IsBusy) 
     { 
      _WebClient.CancelAsync(); 
      _UpdateNews = true; 
     } 
     else 
     { 
      UpdateNews(); 
     } 
    } 

    private void UpdateNews() 
    { 
     _WebClient.DownloadStringAsync(new Uri("http://stackoverflow.com/questions/7084948/c-concurrent-i-o-operations-exception")); 
    } 
} 
+0

非常感謝您的理解。 – FrankCap

+0

如果刷新是取消當前操作的唯一原因,則可能需要刪除_UpdateNews字段並使用e.Cancelled。我沒有將它包含在我的剪輯中以使其更一般化。 – StanislawSwierc