2011-10-17 82 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是您的首选窗口,最好。