2011-10-17 72 views
0

我下面這個線程C# Async WebRequests: Perform Action When All Requests Are CompletedWPF STA線程錯誤

在我的WPF應用程序,我需要異步地從服務器上下載圖像給出的代碼。不過,我得到以下錯誤

The calling thread must be STA, because many UI components require this.

難道是因爲我在主線程上做UI更新?我也宣佈調用線程的狀態STA,我的代碼如下:

private void FixedDocument_Loaded(object sender, RoutedEventArgs e) 
    { 
     Thread t = new Thread(new ThreadStart(AsyncLoadImages)); 
     t.IsBackground = true; 
     t.SetApartmentState(ApartmentState.STA); 
     t.Start(); 
     t.Join(); 
    } 

    private void AsyncLoadImages() 
    { 
     foreach (string resFile in resFiles) 
     { 
      string imageuri = @"http://www.example.com/image.jpg"; 

      WebRequest request = HttpWebRequest.Create(imageuri); 
      request.Method = "GET"; 
      object data = new object(); 
      RequestState state = new RequestState(request, data); 

      IAsyncResult result = request.BeginGetResponse(
       new AsyncCallback(UpdateItem), state); 

      ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(ScanTimeoutCallback), state, (30 * 1000), true); 
     } 
    } 

    private static void ScanTimeoutCallback(object state, bool timedOut) 
    { 
     if (timedOut) 
     { 
      RequestState reqState = (RequestState)state; 
      if (reqState != null) 
      { 
       reqState.Request.Abort(); 
      } 
      Console.WriteLine("aborted- timeout"); 
     } 
    } 

    private void UpdateItem(IAsyncResult result) 
    { 
     RequestState state = (RequestState)result.AsyncState; 
     WebRequest request = (WebRequest)state.Request; 

     HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);   

     BitmapImage bi = new BitmapImage(); 
     bi.BeginInit(); 

     bi.StreamSource = response.GetResponseStream();       
     bi.EndInit(); 

     Image i = new Image(); //hitting the error at this line 
    i.Source = bi; 
    } 

請有人可以幫忙嗎?

非常感謝

+0

此外,調用`t.Join()`會阻塞UI線程 – 2011-10-17 13:32:37

回答

0

你需要調用在MainThread每一個UI操作我想你的updateItem方法不會在UI線程調用這樣你得到這個例外。

我會改變兩兩件事:

首先,使用BackgroundWorker類,這使得這種在WPF異步操作簡單,很多的。其次,如果您有另一個線程(Backgroundworker或自定義線程),則每次UI操作都必須在主線程中執行Dispatch

0

你可以嘗試在下面包裝你的代碼,但這是骯髒的解決方案。

MyUIElement.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => 
{ 

    //your code here 

})); 

如果MyUIElement是您的首選窗口,最好。