在下面的代码中我将一些图像转换为另一个线程上的二进制格式,但是我的UI线程仍然冻结,它应该只显示每个转换后的项目(保存ByteImage的ObservableCollection)。
在UI线程有时间将每个对象添加到ObservableCollection之前,似乎正在转换图像!
有什么问题?我注意到如果我添加Sleep(4)它会平滑地显示图像。
Task.Factory.StartNew(() =>
{
// Generate List of images to upload
var files = Directory.EnumerateFiles(sel.Name, "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".jpeg") || s.EndsWith(".jpg") || s.EndsWith(".png"));
int b = 0;
if (files.Count() > 0)
{
foreach (string item in files)
{
// Generate new name
string oldname = Path.GetFileNameWithoutExtension(item);
string newName = Common.Security.KeyGenerator.GetUniqueKey(32);
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
Filenames.Add(
new NFile
{
OldName = oldname,
NewName = newName
});
}));
}
// Manage each image
foreach (string item in files)
{
// Generate thumbnail byte array
var img = GenerateThumbnailBinary(item);
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
UploadProgress = (int)Math.Round((double)(100 * b / files.Count()));
Thumbnails.Add(new ByteImage { Image = img });
}));
b++;
//System.Threading.Thread.Sleep(40);
}
}
});
编辑: 我现在收到以下错误,我假设我只是设置了我要添加到任务线程的一行代码?然后当它完成时执行Dispatcher?
错误: 严重性代码描述项目文件行
非静态字段,方法或者需要对象引用 property'Dispatcher.Invoke(Action)'
代码:
// Manage each image
ByteImage img = new ByteImage();
foreach (string item in files)
{
// Generate thumbnail byte array
var task = Task.Run(() =>
{
img.Image = GenerateThumbnailBinary(item);
});
task.ContinueWith((t) =>
{
Dispatcher.Invoke(() =>
{
Thumbnails.Add(img);
});
});
UploadProgress = (int)Math.Round((double)(100 * b / files.Count()));
b++;
答案 0 :(得分:1)
您可能需要考虑使用async await运算符来使用Task对象的最新方法。
http://blog.stephencleary.com/2012/02/async-and-await.html
您实际上正在向UI发送代码中发生的任何进展。从技术上讲,我认为它仍在同步运行。 尝试使用continuewith进行如下调度:
var task = Task.Run(() =>
{
//simulate long operation
Thread.Sleep(3000);
});
task.ContinueWith((t) =>
{
Dispatcher.Invoke(() =>
{
//do all UI operations here
});
});
我相信当您使用IProgress对象而不是使用调度程序更新UI时,您还可以保存大量代码。