2011-08-16 1 views
1

내 WP7 응용 프로그램에서 뉴스를 업데이트하는 새로 고침 단추가 있습니다. 내가 두 번이나 새로 고침 버튼 삼중 클릭 내가 오류를 얻고 때 요청 트리플 시간을 보내고이 충돌하고 있기 때문에C# - 동시 I/O 작업 예외

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

나는 그게 생각합니다. 여기 내 클릭 코드입니다.

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

"프로세스를 사용 중이면 취소 할 수 있습니까?"

+0

소개 개인용 bool 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

나는 이것을 조사 할 것이다. Btw, UpdateNews()가 newsWebClient.DownloadStringAsync 피드를 다운로드합니다 (새 Uri ("http://feeds.bbci.co.uk/news/rss.xml")). – FrankCap

2

WebClient는 매우 유연하지 않지만 실제로 사용하려는 경우 IsBusy 속성을 사용하고 진행중인 작업을 취소 할 수 있습니다. 그런 다음 취소되면 다시 시작할 수 있습니다. 동기화에는 중요한 문제가 있습니다. IsBusy를 검사하고 CancelAsync를 호출하는 작업은 원자 적이지 않습니다. 다행히도 DownloadStringCompleted는 UI 스레드에 전달되므로 동기화에 신경 쓸 필요가 없습니다. 아래 스 니펫은 어떻게 달성 할 수 있는지 보여줍니다. 단순성을 위해 Windows Forms입니다.

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