UI冻结/尝试使用任务/异步等待

本文关键字:任务 异步 等待 冻结 UI | 更新日期: 2023-09-27 18:21:35

我编写了一个WPF程序,用于读取PC的配置。

程序必须刷新,HttpWebRequest将延迟代码,因此UI将空闲。

我尝试使用async/await task s。

Class网络中的方法:

public TreeView CreatTVURLs()
{
    TreeView TVURLs = new TreeView(); //Here it will break. Says no STA-Thread
    List<CPingables> lURLs = new List<CPingables>();
    lURLs = ReadURLsFromFile();
    TVURLs.Name = "URLs";
    TVURLs.Background = System.Windows.Media.Brushes.Transparent;
    TVURLs.BorderThickness = new Thickness(0);
    foreach (CPingables item in lURLs)
    {
        tviURL.Items.Add("IP:'t't't" + item.IP.ToString());
        tviURL.Items.Add("URL:'t't't" + item.URL);
        ... more stuff

尝试使用ThreadMainWindow:中的代码

 public async void openWindow()
 {
   TreeView tvURLs = new TreeView();
   tvURLs = (TreeView) TreeViewTest();
   //tvURLs = Network.CreatTVURLs();
   StackPanel.Children.Add(tvURLs);
 }
 private TreeView TreeViewTest()
 {
   TreeView tvURLs = new TreeView();
   Thread t = new Thread(() => { tvURLs = Network.CreatTVURLs(); });
   t.SetApartmentState(ApartmentState.STA);
   t.Start();
   t.Join();
   return tvURLs;
 }

尝试使用Task:

public async void openWindow()
{
  TreeView tvURLs = new TreeView();
  tvURLs = (TreeView) await TreeViewTest();
  Task.WaitAll();
  StackPanel.Children.Add(tvURLs);
}
private Task<TreeView> TreeViewTest()
{
  TreeView tv = new TreeView();
  return Task.Factory.StartNew(() => { tv=(TreeView)Network.CreatTVURLs()});
}

我总是说它必须给我一个STA线程来处理Form项目。

编辑:

HttpWebRequest

 public async void pingIP()
    {
        try
        {
            if (_IPPingAvailible == true)
            {
                Ping pinger = new Ping();
                PingReply replyIP = pinger.Send(_IP);
                _PingByIP = replyIP.Status == IPStatus.Success;
            }
        }
        catch (Exception)
        {
            _PingByIP = false;
        }
        try
        {
            if (_UrlAvailible == true)
            {
                var uriBuilder = new UriBuilder(_URL);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriBuilder.Uri);
                request.Timeout = 1000;                 
                using (var response = await request.GetResponseAsync() as HttpWebResponse)
                {
                    if (response != null && response.StatusCode == HttpStatusCode.OK)
                    {
                        _ReachableByHttp = true;
                    }
                    else
                    {
                        _ReachableByHttp = false;
                    }
                }                    
            }
        }
        catch
        {
            _ReachableByHttp = false;
        }
    }

UI冻结/尝试使用任务/异步等待

规则是,您只能在UI线程(也称为Dispatcher线程或主线程)中访问UI元素。你违反了这个规则。您已通过以下方式插入新线程:Task.Factory.StartNew(...)响应new Thread(...);,但您正在操作新线程内的UI元素(树视图)。

相反,您应该只在新线程中执行I/O操作或HttpRequest/Response,但其他一切(例如,从http响应数据创建树视图)都应该在UI线程中完成。

public async void openWindow()
{
  TreeView tvURLs = await Network.CreatTVURLsAsync();
  StackPanel.Children.Add(tvURLs);
}
public async Task<TreeView> CreatTVURLsAsync()
{
   //you are in dispatcher thread here, so you can access UI elements here
   TreeView TVURLs = new TreeView(); 
   TVURLs.Name = "URLs";
   TVURLs.Background = System.Windows.Media.Brushes.Transparent;
   TVURLs.BorderThickness = new Thickness(0);

   List<CPingables> lURLs = null;
   await Task.Run(() =>
   {
      //you are in new thread now, so you cannot access UI elements here
      lURL = ReadURLsFromFile();
   });
   //you are in dispatcher thread again, so you can access UI elements again
   foreach (CPingables item in lURLs)
   {
      var tviURL = new TreeViewItem();
      ..more stuff
      TVURLs.Items.Add(tviURL);
   }
}