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
尝试使用Thread
:MainWindow
:中的代码
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线程(也称为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);
}
}