我尝试使用WPF
创建图片幻灯片效果
使用新图像更新幻灯片的方法在Windows.Forms.Timer
中每隔几秒调用一次,并在Task
内的自己的线程中运行(如下所示)。
private void LoadImage()
{
Task t = Task.Run(() =>
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
TimeSpan delay = new TimeSpan(0, 0, 0, 0, 0);
Fader.ChangeSource(image, BitmapFromUri(new Uri(compPath + oComps[nCount].name)), delay, delay);
image.Visibility = System.Windows.Visibility.Visible;
mediaElement.Stop();
mediaElement.Close(); ;
mediaElement2.Stop();
mediaElement2.Close();
mediaElement.Visibility = System.Windows.Visibility.Collapsed;
mediaElement2.Visibility = System.Windows.Visibility.Collapsed;
imageLoop.Interval = oComps[nCount].duration;
nCount++;
imageLoop.Start();
}));
});
}
同时,在画布的底部有一个滚动的文本横幅。这也是在它自己的线程中运行,通过Dispatcher
更新UI。
每个图像,滚动文本和幻灯片都将暂停一两秒,似乎在等待图像加载。这种行为是出乎意料的,因为每个元素都在一个单独的线程中。
这可能是更新UI线程的两个Task线程之间的冲突吗?
可能导致这种情况的原因是什么?
答案 0 :(得分:6)
将代码放在另一个线程上的代码不会将工作放在另一个线程上。您的BeginInvoke
正在将其发送回UI线程,您的所有工作都在那里完成。
在执行BeginInvoke调用之前执行繁重的工作,以便工作实际发生在后台线程上。
private void LoadImage()
{
Task t = Task.Run(() =>
{
//I assume BitmapFromUri is the slow step.
var bitmap = BitmapFromUri(new Uri(compPath + oComps[nCount].name);
//Now that we have our bitmap, now go to the main thread.
this.Dispatcher.BeginInvoke((Action)(() =>
{
TimeSpan delay = new TimeSpan(0, 0, 0, 0, 0);
//I assume Fader is a control and must be on the UI thread, if not then move that out of the BeginInvoke too.
Fader.ChangeSource(image, bitmap), delay, delay);
image.Visibility = System.Windows.Visibility.Visible;
mediaElement.Stop();
mediaElement.Close(); ;
mediaElement2.Stop();
mediaElement2.Close();
mediaElement.Visibility = System.Windows.Visibility.Collapsed;
mediaElement2.Visibility = System.Windows.Visibility.Collapsed;
imageLoop.Interval = oComps[nCount].duration;
nCount++;
imageLoop.Start();
}));
});
我怀疑你的横幅广告实际上并没有在另一个帖子上工作,你可能想要查看它。
如果可能的话,更好的解决方法是将BitmapFromUri重写为异步并且根本不使用线程。
private async Task LoadImageAsync()
{
TimeSpan delay = new TimeSpan(0, 0, 0, 0, 0);
var bitmap = await BitmapFromUriAsync(new Uri(compPath + oComps[nCount].name);
Fader.ChangeSource(image, bitmap), delay, delay);
image.Visibility = System.Windows.Visibility.Visible;
mediaElement.Stop();
mediaElement.Close(); ;
mediaElement2.Stop();
mediaElement2.Close();
mediaElement.Visibility = System.Windows.Visibility.Collapsed;
}