我有下面的代码时运行块更新的UI。
ProcessDocumentRange方法的工作是在一个范围内循环,并调用BuildDocumentList方法,以便为循环的每次迭代添加对List的文档引用。
public List<Document> _queuedDocuments = new List<Document>();
public string _instID = "";
static String _dest = "c:\\test";
static Int32 _startId = 50001;
static Int32 _endId = 65001;
private async void _btnStartClick(object sender, EventArgs e)
{
await ProcessRecords();
}
private async Task ProcessRecords()
{
// Call to Method which freezes UI
await ProcessDocumentRange(_startId, _dest);
}
public async Task ProcessDocumentRange(int _startID, string _root)
{
int year = 28;
for (int i = _startID; i < _endId; i++) //Start of loop that freezes UI
{
_instID = year.ToString() + i.ToString().PadLeft(5, '0');
await BuildDocumentList(year, i, _instID, _root);
}
}
private async Task BuildDocumentList(int year, int image, string instID, string root)
{
string documentIndexFile = root + year.ToString() + "\\" + instID + ".txt";
if (!File.Exists(documentIndexFile))
_queuedDocuments.Add(new Document { Year = year, Image = image });
}
我试着像下面这样调用方法,UI没有冻结,但是循环退出,并且永远不会构建列表:await Task.Run(() => ProcessDocumentRange(_startId, _dest));
任何帮助都将不胜感激。
更新现在抛出Exception的代码:调用线程必须是STA,因为许多UI组件都要求此线程。
public partial class MainWindow : Window
{
public List<Document> _queuedDocuments = new List<Document>();
public MainWindow()
{
InitializeComponent();
_tbURL.Text = _url;
_tbDest.Text = _dest;
_tbStartId.Text = _startId.ToString();
_tbEndID.Text = _endId.ToString();
}
private async void _btnStartClick(object sender, EventArgs e)
{
await ProcessDocumentRange(_startId, _dest);
}
public async Task ProcessDocumentRange(int _startID, string _root)
{
//Exception thrown at await Task.Run below.
//Exception may have something to do with adding an item to the list
await Task.Run(() =>
{
int year = 28;
for (int i = _startID; i < _endId; i++)
{
_instID = year.ToString() + i.ToString().PadLeft(5, '0');
BuildDocumentList(year, i, _instID, _root);
}
});
}
private void BuildDocumentList(int year, int image, string instID, string root)
{
string documentIndexFile = root + year.ToString() + "\\" + instID + ".txt";
if (!File.Exists(documentIndexFile))
_queuedDocuments.Add(new Document { Year = year, Image = image });
}
//Document Class
public class Document : MainWindow
{
private int _year = -1;
public int Year
{
get
{
return _year;
}
set
{
_year = value;
}
}
private int _image = -1;
public int Image
{
get
{
return _image;
}
set
{
_image = value;
}
}
}
1条答案
按热度按时间3z6pesqy1#
您的方法是同步执行的,因为它们都没有返回实际的
Task
。但最重要的是,您未能达到目标,因为您没有卸载CPU密集型工作以减轻UI线程的负担。正是这个循环仍然耗尽UI线程,因此冻结了UI。要将其移动到不同的线程(后台线程),必须调用
Task.Run
:如果在列表填充后没有任何事情要做,则不必使用
await
。只需创建后台线程并返回到UI线程并继续: